int main(int argc, char *argv[]) { listelem_alloc_t *le; struct bogus *bogus1, *bogus2; int i; TEST_ASSERT(le = listelem_alloc_init(sizeof(struct bogus))); bogus1 = listelem_malloc(le); bogus1->str = "hello"; bogus1->foobie = 42; bogus2 = listelem_malloc(le); bogus2->str = "goodbye"; bogus2->foobie = 69; TEST_EQUAL(bogus1->foobie, 42); TEST_EQUAL(0, strcmp(bogus1->str, "hello")); listelem_free(le, bogus1); listelem_free(le, bogus2); listelem_alloc_free(le); TEST_ASSERT(le = listelem_alloc_init(sizeof(struct bogus))); listelem_stats(le); for (i = 0; i < 60; ++i) bogus1 = listelem_malloc(le); listelem_stats(le); listelem_alloc_free(le); { struct bogus *bogus[600]; int32 bogus_id[600]; le = listelem_alloc_init(sizeof(struct bogus)); for (i = 0; i < 600; ++i) bogus[i] = listelem_malloc_id(le, bogus_id + i); listelem_stats(le); for (i = 0; i < 600; ++i) { TEST_EQUAL(bogus[i], listelem_get_item(le, bogus_id[i])); } for (i = 0; i < 600; ++i) listelem_free(le, bogus[i]); listelem_stats(le); for (i = 0; i < 600; ++i) bogus[i] = listelem_malloc_id(le, bogus_id + i); listelem_stats(le); for (i = 0; i < 600; ++i) TEST_EQUAL(bogus[i], listelem_get_item(le, bogus_id[i])); listelem_alloc_free(le); } return 0; }
/** * Free HMM network for one utterance of fwdflat search. */ static void destroy_fwdflat_chan(ngram_search_t *ngs) { int32 i, wid; for (i = 0; ngs->fwdflat_wordlist[i] >= 0; i++) { root_chan_t *rhmm; chan_t *thmm; wid = ngs->fwdflat_wordlist[i]; if (dict_is_single_phone(ps_search_dict(ngs),wid)) continue; assert(ngs->word_chan[wid] != NULL); /* The first HMM in ngs->word_chan[wid] was allocated with * ngs->root_chan_alloc, but this will attempt to free it * using ngs->chan_alloc, which will not work. Therefore we * free it manually and move the list forward before handing * it off. */ rhmm = (root_chan_t *)ngs->word_chan[wid]; thmm = rhmm->next; listelem_free(ngs->root_chan_alloc, rhmm); ngs->word_chan[wid] = thmm; ngram_search_free_all_rc(ngs, wid); } }
static void hyp_free (hyp_t *list) { hyp_t *h; while (list) { h = list->next; listelem_free ((char *)list, sizeof(hyp_t)); list = h; } }
static void slinks_free (slink_t *l) { slink_t *tmp; while (l) { tmp = l->next; listelem_free ((char *) l, sizeof(slink_t)); l = tmp; } }
/* Free all allocated pnodes */ static void pnodes_free ( void ) { pnode_t *p; while (pnode_list) { p = pnode_list->alloc_next; listelem_free ((char *) pnode_list, sizeof(pnode_t)); pnode_list = p; } }
static void delete_unreachable ( void ) { latnode_t *node, *t_node, *prev_node; latlink_t *link, *t_link; prev_node = NULL; for (node = latnode_list; node; node = t_node) { t_node = node->next; if (! node->reachable) { /* Node and its links can be removed */ if (prev_node) prev_node->next = node->next; else latnode_list = node->next; for (link = node->links; link; link = t_link) { t_link = link->next; listelem_free (link, sizeof(latlink_t)); } listelem_free (node, sizeof(latnode_t)); } else prev_node = node; } }
/** * Destroy wordlist from the current utterance. */ static void destroy_fwdflat_wordlist(ngram_search_t *ngs) { ps_latnode_t *node, *tnode; int32 f; if (!ngs->fwdtree) return; for (f = 0; f < ngs->n_frame; f++) { for (node = ngs->frm_wordlist[f]; node; node = tnode) { tnode = node->next; listelem_free(ngs->latnode_alloc, node); } } }
/* * Remove src->dst link and return the associated prob. */ static int32 un_slink_succ (snode_t *src, snode_t *dst) { slink_t *l, *prevl; int32 prob; /* Find link from src to dst */ prevl = NULL; for (l = src->succlist; l && (l->node != dst); l = l->next) prevl = l; assert (l); /* The link must exist */ if (! prevl) src->succlist = l->next; else prevl->next = l->next; prob = l->prob; listelem_free ((char *)l, sizeof(slink_t)); return prob; }
static void bypass_filler_nodes ( void ) { latnode_t *node, *to, *from, *prev_node, *t_node; latlink_t *link, *f_link, *t_link, *prev_link; rev_latlink_t *revlink, *t_revlink; int32 score; /* Create reverse links for all links pointing to filler nodes */ for (node = latnode_list; node; node = node->next) { for (link = node->links; link; link = link->next) { to = link->to; if (ISA_FILLER_WORD(to->wid)) { revlink = (rev_latlink_t *) listelem_alloc (sizeof (rev_latlink_t)); revlink->link = link; revlink->next = to->revlinks; to->revlinks = revlink; } } } /* Bypass filler nodes */ for (node = latnode_list; node; node = node->next) { if (! ISA_FILLER_WORD(node->wid)) continue; /* Replace each link entering filler node with links to all its successors */ for (revlink = node->revlinks; revlink; revlink = revlink->next) { link = revlink->link; /* link entering filler node */ from = link->from; score = (node->wid == sil_wid) ? sil_pen : filler_pen; score += link->link_scr; /* * Make links from predecessor of filler (from) to successors of filler. * But if successor is a filler, it has already been eliminated since it * appears earlier in latnode_list (see build...). So it can be skipped. * Likewise, no reverse links needed for the new links; none of them * points to a filler node. */ for (f_link = node->links; f_link; f_link = f_link->next) { if (! ISA_FILLER_WORD(f_link->to->wid)) link_latnodes (from, f_link->to, score + f_link->link_scr, link->ef); } } } /* Delete filler nodes and all links and reverse links from it */ prev_node = NULL; for (node = latnode_list; node; node = t_node) { t_node = node->next; if (ISA_FILLER_WORD(node->wid)) { for (revlink = node->revlinks; revlink; revlink = t_revlink) { t_revlink = revlink->next; revlink->link->to = NULL; listelem_free (revlink, sizeof(rev_latlink_t)); } for (link = node->links; link; link = t_link) { t_link = link->next; listelem_free (link, sizeof(latlink_t)); } if (prev_node) prev_node->next = t_node; else latnode_list = t_node; listelem_free (node, sizeof(latnode_t)); } else prev_node = node; } /* Reclaim links pointing nowhere */ for (node = latnode_list; node; node = node->next) { prev_link = NULL; for (link = node->links; link; link = t_link) { t_link = link->next; if (link->to == NULL) { if (prev_link) prev_link->next = t_link; else node->links = t_link; listelem_free (link, sizeof(latlink_t)); } else prev_link = link; } } }
/** * Find all active words in backpointer table and sort by frame. */ static void build_fwdflat_wordlist(ngram_search_t *ngs) { int32 i, f, sf, ef, wid, nwd; bptbl_t *bp; ps_latnode_t *node, *prevnode, *nextnode; /* No tree-search, use statically allocated wordlist. */ if (!ngs->fwdtree) return; memset(ngs->frm_wordlist, 0, ngs->n_frame_alloc * sizeof(*ngs->frm_wordlist)); /* Scan the backpointer table for all active words and record * their exit frames. */ for (i = 0, bp = ngs->bp_table; i < ngs->bpidx; i++, bp++) { sf = (bp->bp < 0) ? 0 : ngs->bp_table[bp->bp].frame + 1; ef = bp->frame; wid = bp->wid; /* Anything that can be transitioned to in the LM can go in * the word list. */ if (!ngram_model_set_known_wid(ngs->lmset, dict_basewid(ps_search_dict(ngs), wid))) continue; /* Look for it in the wordlist. */ for (node = ngs->frm_wordlist[sf]; node && (node->wid != wid); node = node->next); /* Update last end frame. */ if (node) node->lef = ef; else { /* New node; link to head of list */ node = listelem_malloc(ngs->latnode_alloc); node->wid = wid; node->fef = node->lef = ef; node->next = ngs->frm_wordlist[sf]; ngs->frm_wordlist[sf] = node; } } /* Eliminate "unlikely" words, for which there are too few end points */ for (f = 0; f < ngs->n_frame; f++) { prevnode = NULL; for (node = ngs->frm_wordlist[f]; node; node = nextnode) { nextnode = node->next; /* Word has too few endpoints */ if ((node->lef - node->fef < ngs->min_ef_width) || /* Word is </s> and doesn't actually end in last frame */ ((node->wid == ps_search_finish_wid(ngs)) && (node->lef < ngs->n_frame - 1))) { if (!prevnode) ngs->frm_wordlist[f] = nextnode; else prevnode->next = nextnode; listelem_free(ngs->latnode_alloc, node); } else prevnode = node; } } /* Form overall wordlist for 2nd pass */ nwd = 0; bitvec_clear_all(ngs->word_active, ps_search_n_words(ngs)); for (f = 0; f < ngs->n_frame; f++) { for (node = ngs->frm_wordlist[f]; node; node = node->next) { if (!bitvec_is_set(ngs->word_active, node->wid)) { bitvec_set(ngs->word_active, node->wid); ngs->fwdflat_wordlist[nwd++] = node->wid; } } } ngs->fwdflat_wordlist[nwd] = -1; E_INFO("Utterance vocabulary contains %d words\n", nwd); }
/* * All frames consumed. Trace back best Viterbi state sequence and dump it out. */ int32 align_end_utt (align_stseg_t **stseg_out, align_phseg_t **phseg_out, align_wdseg_t **wdseg_out) { slink_t *l; snode_t *s; history_t *h, *ph, *nh; align_stseg_t *stseg; align_phseg_t *phseg; align_wdseg_t *wdseg; /* Free up previous result, if any */ while (align_stseg) { stseg = align_stseg->next; listelem_free ((char *) align_stseg, sizeof(align_stseg_t)); align_stseg = stseg; } while (align_phseg) { phseg = align_phseg->next; listelem_free ((char *) align_phseg, sizeof(align_phseg_t)); align_phseg = phseg; } while (align_wdseg) { wdseg = align_wdseg->next; listelem_free ((char *) align_wdseg, sizeof(align_wdseg_t)); align_wdseg = wdseg; } /* First find best ending history and link to stail */ stail.score = (int32)0x80000000; stail.hist = NULL; for (l = stail.predlist; l; l = l->next) { s = l->node; if ((s->active_frm == curfrm) && (s->score + l->prob > stail.score)) { stail.score = s->score + l->prob; stail.hist = s->hist; } } if (stail.hist) { /* Reverse the best Viterbi path (back trace) so it is forward in time */ nh = NULL; for (h = stail.hist; h; h = ph) { ph = h->pred; h->pred = nh; nh = h; } /* Trace state, phone, and word segmentations */ build_stseg (nh); build_phseg (nh); build_wdseg (nh); } *stseg_out = align_stseg; *phseg_out = align_phseg; *wdseg_out = align_wdseg; /* delete history list */ while (hist_head) { h = hist_head->alloc_next; listelem_free ((char *) hist_head, sizeof(history_t)); hist_head = h; } return (stail.hist ? 0 : -1); }