45 #include <sphinxbase/ckd_alloc.h>
64 ckd_free(al->word.seq);
65 ckd_free(al->sseq.seq);
66 ckd_free(al->state.seq);
71 #define VECTOR_GROW 10
73 vector_grow_one(
void *ptr, uint16 *n_alloc, uint16 *n,
size_t item_size)
76 if (newsize < *n_alloc) {
80 newsize += VECTOR_GROW;
83 ptr = ckd_realloc(ptr, newsize * item_size);
93 ptr = vector_grow_one(vec->seq, &vec->n_alloc,
94 &vec->n_ent,
sizeof(*vec->seq));
98 return vec->seq + vec->n_ent - 1;
109 int32 wid,
int duration)
113 if ((ent = ps_alignment_vector_grow_one(&al->word)) == NULL)
116 if (al->word.n_ent > 1)
117 ent->start = ent[-1].start + ent[-1].duration;
120 ent->duration = duration;
122 ent->parent = PS_ALIGNMENT_NONE;
123 ent->child = PS_ALIGNMENT_NONE;
125 return al->word.n_ent;
137 ps_alignment_vector_empty(&al->sseq);
138 ps_alignment_vector_empty(&al->state);
144 lc = bin_mdef_silphone(mdef);
145 for (i = 0; i < al->word.n_ent; ++i) {
148 int wid = went->id.wid;
149 int len = dict_pronlen(dict, wid);
152 if (i < al->word.n_ent - 1)
153 rc = dict_first_phone(dict, al->word.seq[i+1].id.wid);
155 rc = bin_mdef_silphone(mdef);
158 if ((sent = ps_alignment_vector_grow_one(&al->sseq)) == NULL) {
159 E_ERROR(
"Failed to add phone entry!\n");
162 sent->id.pid.cipid = dict_first_phone(dict, wid);
163 sent->id.pid.tmatid = bin_mdef_pid2tmatid(mdef, sent->id.pid.cipid);
164 sent->start = went->start;
165 sent->duration = went->duration;
168 went->child = (uint16)(sent - al->sseq.seq);
171 = dict2pid_lrdiph_rc(d2p, sent->id.pid.cipid, lc, rc);
174 = dict2pid_ldiph_lc(d2p, sent->id.pid.cipid,
175 dict_second_phone(dict, wid), lc);
176 assert(sent->id.pid.ssid !=
BAD_SSID);
179 for (j = 1; j < len - 1; ++j) {
180 if ((sent = ps_alignment_vector_grow_one(&al->sseq)) == NULL) {
181 E_ERROR(
"Failed to add phone entry!\n");
184 sent->id.pid.cipid =
dict_pron(dict, wid, j);
185 sent->id.pid.tmatid = bin_mdef_pid2tmatid(mdef, sent->id.pid.cipid);
187 assert(sent->id.pid.ssid !=
BAD_SSID);
188 sent->start = went->start;
189 sent->duration = went->duration;
197 assert(j == len - 1);
198 if ((sent = ps_alignment_vector_grow_one(&al->sseq)) == NULL) {
199 E_ERROR(
"Failed to add phone entry!\n");
202 sent->id.pid.cipid = dict_last_phone(dict, wid);
203 sent->id.pid.tmatid = bin_mdef_pid2tmatid(mdef, sent->id.pid.cipid);
205 dict_second_last_phone(dict, wid));
206 sent->id.pid.ssid = rssid->
ssid[rssid->
cimap[rc]];
207 assert(sent->id.pid.ssid !=
BAD_SSID);
208 sent->start = went->start;
209 sent->duration = went->duration;
215 lc = dict_last_phone(dict, wid);
221 for (i = 0; i < al->sseq.n_ent; ++i) {
226 for (j = 0; j < bin_mdef_n_emit_state(mdef); ++j) {
227 if ((sent = ps_alignment_vector_grow_one(&al->state)) == NULL) {
228 E_ERROR(
"Failed to add state entry!\n");
231 sent->id.senid = bin_mdef_sseq2sen(mdef, pent->id.pid.ssid, j);
233 sent->start = pent->start;
234 sent->duration = pent->duration;
238 pent->child = (uint16)(sent - al->state.seq);
255 ps_alignment_vector_empty(&al->sseq);
256 ps_alignment_vector_empty(&al->state);
262 for (i = 0; i < al->word.n_ent; ++i) {
265 int wid = went->id.wid;
266 int len = dict_pronlen(dict, wid);
269 for (j = 0; j < len; ++j) {
270 if ((sent = ps_alignment_vector_grow_one(&al->sseq)) == NULL) {
271 E_ERROR(
"Failed to add phone entry!\n");
274 sent->id.pid.cipid =
dict_pron(dict, wid, j);
275 sent->id.pid.tmatid = bin_mdef_pid2tmatid(mdef, sent->id.pid.cipid);
276 sent->id.pid.ssid = bin_mdef_pid2ssid(mdef, sent->id.pid.cipid);
277 assert(sent->id.pid.ssid !=
BAD_SSID);
278 sent->start = went->start;
279 sent->duration = went->duration;
288 for (i = 0; i < al->sseq.n_ent; ++i) {
293 for (j = 0; j < bin_mdef_n_emit_state(mdef); ++j) {
294 if ((sent = ps_alignment_vector_grow_one(&al->state)) == NULL) {
295 E_ERROR(
"Failed to add state entry!\n");
298 sent->id.senid = bin_mdef_sseq2sen(mdef, pent->id.pid.ssid, j);
300 sent->start = pent->start;
301 sent->duration = pent->duration;
305 pent->child = (uint16)(sent - al->state.seq);
319 for (i = 0; i < al->state.n_ent; ++i) {
322 if (pent != last_ent) {
323 pent->start = sent->start;
327 pent->duration += sent->duration;
328 pent->score += sent->score;
334 for (i = 0; i < al->sseq.n_ent; ++i) {
337 if (went != last_ent) {
338 went->start = pent->start;
342 went->duration += pent->duration;
343 went->score += pent->score;
353 return (
int)al->word.n_ent;
359 return (
int)al->sseq.n_ent;
365 return (
int)al->state.n_ent;
373 if (al->word.n_ent == 0)
375 itor = ckd_calloc(1,
sizeof(*itor));
377 itor->vec = &al->word;
387 if (al->sseq.n_ent == 0)
389 itor = ckd_calloc(1,
sizeof(*itor));
391 itor->vec = &al->sseq;
401 if (al->state.n_ent == 0)
403 itor = ckd_calloc(1,
sizeof(*itor));
405 itor->vec = &al->state;
413 return itor->vec->seq + itor->pos;
428 if (pos >= itor->vec->n_ent) {
441 if (++itor->pos >= itor->vec->n_ent) {
453 if (--itor->pos < 0) {
466 if (itor->vec == &itor->al->word)
468 if (itor->vec->seq[itor->pos].parent == PS_ALIGNMENT_NONE)
470 itor2 = ckd_calloc(1,
sizeof(*itor2));
471 itor2->al = itor->al;
472 itor2->pos = itor->vec->seq[itor->pos].parent;
473 if (itor->vec == &itor->al->sseq)
474 itor2->vec = &itor->al->word;
476 itor2->vec = &itor->al->sseq;
486 if (itor->vec == &itor->al->state)
488 if (itor->vec->seq[itor->pos].child == PS_ALIGNMENT_NONE)
490 itor2 = ckd_calloc(1,
sizeof(*itor2));
491 itor2->al = itor->al;
492 itor2->pos = itor->vec->seq[itor->pos].child;
493 if (itor->vec == &itor->al->word)
494 itor2->vec = &itor->al->sseq;
496 itor2->vec = &itor->al->state;
int ps_alignment_n_states(ps_alignment_t *al)
Number of states.
int ps_alignment_populate_ci(ps_alignment_t *al)
Populate lower layers using context-independent phones.
ps_alignment_t * ps_alignment_init(dict2pid_t *d2p)
Create a new, empty alignment.
ps_alignment_iter_t * ps_alignment_iter_goto(ps_alignment_iter_t *itor, int pos)
Move alignment iterator to given index.
#define BAD_SSID
Invalid senone sequence ID (limited to 16 bits for PocketSphinx).
ps_alignment_iter_t * ps_alignment_iter_next(ps_alignment_iter_t *itor)
Move an alignment iterator forward.
int dict2pid_free(dict2pid_t *d2p)
Free the memory dict2pid structure.
int ps_alignment_free(ps_alignment_t *al)
Release an alignment.
#define dict2pid_rssid(d, ci, lc)
Access macros; not designed for arbitrary use.
int ps_alignment_propagate(ps_alignment_t *al)
Propagate timing information up from state sequence.
#define BAD_SENID
Invalid senone ID (limited to 16 bits for PocketSphinx).
bin_mdef_t * mdef
Model definition, used to generate internal ssids on the fly.
ps_alignment_iter_t * ps_alignment_words(ps_alignment_t *al)
Iterate over the alignment starting at the first word.
dict_t * dict
Dictionary this table refers to.
a structure for a dictionary.
s3ssid_t dict2pid_internal(dict2pid_t *d2p, int32 wid, int pos)
Return the senone sequence ID for the given word position.
cross word triphone model structure
dict2pid_t * dict2pid_retain(dict2pid_t *d2p)
Retain a pointer to dict2pid.
ps_alignment_iter_t * ps_alignment_iter_prev(ps_alignment_iter_t *itor)
Move an alignment iterator back.
ps_alignment_iter_t * ps_alignment_states(ps_alignment_t *al)
Iterate over the alignment starting at the first state.
ps_alignment_iter_t * ps_alignment_iter_up(ps_alignment_iter_t *itor)
Get a new iterator starting at the parent of the current node.
ps_alignment_iter_t * ps_alignment_iter_down(ps_alignment_iter_t *itor)
Get a new iterator starting at the first child of the current node.
int ps_alignment_n_phones(ps_alignment_t *al)
Number of phones.
int ps_alignment_iter_free(ps_alignment_iter_t *itor)
Release an iterator before completing all iterations.
s3cipid_t * cimap
Index into ssid[] above for each ci phone.
Multi-level alignment structure.
int ps_alignment_populate(ps_alignment_t *al)
Populate lower layers using available word information.
#define dict_pron(d, w, p)
The CI phones of the word w at position p.
ps_alignment_iter_t * ps_alignment_phones(ps_alignment_t *al)
Iterate over the alignment starting at the first phone.
Building composite triphone (as well as word internal triphones) with the dictionary.
s3ssid_t * ssid
Senone Sequence ID list for all context ciphones.
int ps_alignment_add_word(ps_alignment_t *al, int32 wid, int duration)
Append a word.
ps_alignment_entry_t * ps_alignment_iter_get(ps_alignment_iter_t *itor)
Get the alignment entry pointed to by an iterator.
int ps_alignment_n_words(ps_alignment_t *al)
Number of words.