/** * @file rdhmmdef_tiedmix.c * * * @brief HTK %HMM 定義ファイルの読み込み:tied-mixtureモデルの混合分布コードブック * * * * @brief Read HTK %HMM definition file: mixture codebook in tied-mixture model * * * @author Akinobu LEE * @date Wed Feb 16 03:25:11 2005 * * $Revision: 1.6 $ * */ /* * Copyright (c) 1991-2012 Kawahara Lab., Kyoto University * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology * Copyright (c) 2005-2012 Julius project team, Nagoya Institute of Technology * All rights reserved */ #include #include extern char *rdhmmdef_token; ///< Current token /** * Look up a data macro by the name. * * @param hmm [in] %HMM definition data * @param keyname [in] macro name to find * * @return pointer to the found data, or NULL if not found. */ static GCODEBOOK * codebook_lookup(HTK_HMM_INFO *hmm, char *keyname) { GCODEBOOK *book; if (hmm->codebook_root == NULL) return(NULL); book = aptree_search_data(keyname, hmm->codebook_root); if (book != NULL && strmatch(book->name, keyname)) { return book; } else { return NULL; } } /** * Add a new data to the global structure. * * @param hmm [i/o] %HMM definition data to store it * @param new [in] new data to be added */ void codebook_add(HTK_HMM_INFO *hmm, GCODEBOOK *new) { GCODEBOOK *match; if (hmm->codebook_root == NULL) { hmm->codebook_root = aptree_make_root_node(new, &(hmm->mroot)); } else { match = aptree_search_data(new->name, hmm->codebook_root); if (match != NULL && strmatch(match->name, new->name)) { jlog("Error: rdhmmdef_tiedmix: ~s \"%s\" is already defined\n", new->name); rderr(NULL); } else { aptree_add_entry(new->name, new, match->name, &(hmm->codebook_root), &(hmm->mroot)); } } } /** * @brief Convert codebook ID to the defined %HMM density * * This function assigns a list of %HMM density definition to the * given codebook. The densities are searched by the name of * codebook name followed by the mixture component ID starting from 1. * For example, if you have a codebook whose name is "ny4s2m", The densities * of names like "ny4s2m1", "ny4s2m2", ... will be searched through the * %HMM definition data. The resulting list will be stored in the codebook. * * If some density definitions are not found, they are just skipped. * In this case, a warning message will be output to standard error. * * @param hmminfo [in] %HMM definition data that has densities * @param book [i/o] codebook, name given and density list will be stored. */ static void tmix_create_codebook_index(HTK_HMM_INFO *hmminfo, GCODEBOOK *book) { char *mixname; HTK_HMM_Dens *dtmp; int i; int realbooknum = 0; mixname = (char *)mymalloc(strlen(book->name)+30); book->d = (HTK_HMM_Dens **) mybmalloc2(sizeof(HTK_HMM_Dens *) * book->num, &(hmminfo->mroot)); for (i=0;inum;i++) { sprintf(mixname, "%s%d", book->name, i + 1); if ((dtmp = dens_lookup(hmminfo, mixname)) == NULL) { /* * jlog("Error: mixture \"%s\" (%dth mixture in codebook \"%s\") not found\n", mixname, i + 1, book->name); * rderr(NULL); */ book->d[i] = NULL; } else { book->d[i] = dtmp; realbooknum++; } } if (realbooknum < book->num) { jlog("Warning: rdhmmdef_tiedmix: book [%s]: defined=%d < %d\n", book->name, realbooknum, book->num); } free(mixname); } /** * @brief Read a codebook name and weights, build the codebook structure * on demand, and assigns them to the current mixture PDF. * * The required codebook on the current token will be assigned to this * mpdf. If the corresponding codebook structure is not built yet, * it will be constructed here on demand by gathering corresponding mixture * density definitions. Then this mpdf will store the pointer to the * codebook, together with its own mixture weights in the following tokens. * * @param fp [in] file pointer * @param mpdf [i/o] current %HMM mixture PDF to hold pointer to the codebook and their weights * @param hmm [i/o] %HMM definition data, codebook statistics and tied-mixture marker will be modified. */ void tmix_read(FILE *fp, HTK_HMM_PDF *mpdf, HTK_HMM_INFO *hmm) { char *bookname; GCODEBOOK *thebook; int mid, i; NoTokErr("missing TMIX bookname"); bookname = rdhmmdef_token; /* check whether the specified codebook exist */ if ((thebook = codebook_lookup(hmm, bookname)) == NULL) { /* create GCODEBOOK global index structure from mixture macros */ thebook = (GCODEBOOK *)mybmalloc2(sizeof(GCODEBOOK), &(hmm->mroot)); thebook->name = mybstrdup2(bookname, &(hmm->mroot)); thebook->num = mpdf->mix_num; /* map codebook id to HTK_HMM_Dens* */ tmix_create_codebook_index(hmm, thebook); /* register the new codebook */ codebook_add(hmm, thebook); thebook->id = hmm->codebooknum; hmm->codebooknum++; /* set maximum codebook size */ if (hmm->maxcodebooksize < thebook->num) hmm->maxcodebooksize = thebook->num; } else { /* check coherence */ if (mpdf->mix_num != thebook->num) { rderr("tmix_read: TMIX weight num don't match the codebook size"); } } /* set pointer to the GCODEBOOK structure */ mpdf->b = (HTK_HMM_Dens **)thebook; /* store the weights to `mpdf->bweight[]' */ read_token(fp); mpdf->bweight = (PROB *) mybmalloc2(sizeof(PROB) * mpdf->mix_num, &(hmm->mroot)); { int len; double w; mid = 0; while (mid < mpdf->mix_num) { char *p, q; NoTokErr("missing some TMIX weights"); if ((p = strchr(rdhmmdef_token, '*')) == NULL) { len = 1; w = atof(rdhmmdef_token); } else { len = atoi(p+1); q = *p; *p = '\0'; w = atof(rdhmmdef_token); *p = q; } read_token(fp); for(i=0;ibweight[mid] = (PROB)log(w); mid++; } } } /* mark info as tied mixture */ hmm->is_tied_mixture = TRUE; }