1 /**
2 * @file pass1.c
3 *
4 * <JA>
5 * @brief ��1�ѥ����ե졼��Ʊ���ӡ���õ��
6 *
7 * ��Ū�ڹ�¤������Ѥ��ơ�������ħ�̥٥��ȥ�����Ф��ơ�Julius���裱�ѥ�
8 * �Ǥ���ե졼��Ʊ���ӡ���õ����Ԥ��ޤ�.
9 *
10 * ���ϥǡ������Τ����餫���������Ƥ�����ϡ����Ƿ���
11 * �Ԥ��ؿ� get_back_trellis() ���ᥤ��ƤФ�ޤ�. ����饤��ǧ��
12 * �ξ��� realtime_1stpass.c ���顤��������ե졼�ऴ�Ȥη���
13 * ��λ�����Τ��줾�줬���ϤοʹԤˤ��碌�Ƹ��̤˸ƤФ�ޤ�.
14 *
15 * �ºݤθġ���ǧ�������������Ȥν����� beam.c �˵��Ҥ���Ƥ��ޤ�.
16 *
17 * </JA>
18 *
19 * <EN>
20 * @brief The first pass: frame-synchronous beam search
21 *
22 * These functions perform a frame-synchronous beam search using a static
23 * lexicon tree, as the first pass of Julius/Julian.
24 *
25 * When the whole input is already obtained, get_back_trellis() simply
26 * does all the processing of the 1st pass. When performing online
27 * real-time recognition with concurrent speech input, each function
28 * will be called separately from realtime_1stpass.c according on the
29 * basis of input processing.
30 *
31 * The core recognition processing functions for each recognition
32 * process instances are written in beam.c.
33 *
34 * </EN>
35 *
36 * @author Akinobu Lee
37 * @date Fri Oct 12 23:14:13 2007
38 *
39 * $Revision: 1.7 $
40 *
41 */
42 /*
43 * Copyright (c) 1991-2007 Kawahara Lab., Kyoto University
44 * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
45 * Copyright (c) 2005-2007 Julius project team, Nagoya Institute of Technology
46 * All rights reserved
47 */
48
49 #include <julius/julius.h>
50
51 /********************************************************************/
52 /* �裱�ѥ���¹Ԥ���ᥤ��ؿ� */
53 /* ���Ϥ�ѥ��ץ饤������������ realtime_1stpass.c �ȤΤ��� */
54 /* main function to execute 1st pass */
55 /* the pipeline processing is not here: see realtime_1stpass.c */
56 /********************************************************************/
57
58 /**
59 * <EN>
60 * @brief Process one input frame for all recognition process instance.
61 *
62 * This function proceeds the recognition for one frame. All
63 * recognition process instance will be processed synchronously.
64 * The input frame for each instance is stored in mfcc->f, where mfcc
65 * is the MFCC calculation instance assigned to each process instance.
66 *
67 * If an instance's mfcc->invalid is set to TRUE, its processing will
68 * be skipped.
69 *
70 * When using GMM, GMM computation will also be executed here.
71 * If GMM_VAD is defined, GMM-based voice detection will be performed
72 * inside this function, by using a scheme of short-pause segmentation.
73 *
74 * This function also handles segmentation of recognition process. A
75 * segmentation will occur when end of speech is detected by level-based
76 * sound detection or GMM-based / decoder-based VAD, or by request from
77 * application. When segmented, it stores current frame and return with
78 * that status.
79 *
80 * The frame-wise callbacks will be executed inside this function,
81 * when at least one valid recognition process instances exists.
82 *
83 * </EN>
84 * <JA>
85 * @brief ���Ƥ�ǧ����������������1�ե졼��ʬ�ʤ��.
86 *
87 * ���Ƥ�ǧ�����������ˤĤ��ơ�����դ����Ƥ���MFCC��������
88 * �� mfcc->f ���ȥե졼��Ȥ��ƽ�����1�ե졼��ʤ��.
89 *
90 * �ʤ���mfcc->invalid �� TRUE �ȤʤäƤ�����������ν����ϥ����å�
91 * �����.
92 *
93 * GMM�η��⤳���ǸƤӽФ����. GMM_VAD ������ϡ�GMM �ˤ��
94 * ȯ�ö�ֳ��ϡ���λ�θ��Ф������ǹԤ���. �ޤ���GMM�η���̡�
95 * ���뤤��ǧ��������Υ��硼�ȥݡ����������ơ������Ƚ���ǥХ���������
96 * �������ˤ�ꥻ�����ơ�������ᤵ�줿���ɤ�����Ƚ���Ԥ�.
97 *
98 * �ե졼��ñ�̤ǸƤӽФ���륳����Хå�����Ͽ����Ƥ�����ϡ�������
99 * �ƽФ���Ԥ�.
100 * </JA>
101 *
102 * @param recog [in] engine instance
103 *
104 * @return 0 on success, -1 on error, or 1 when an input segmentation
105 * occured/requested inside this function.
106 *
107 * @callgraph
108 * @callergraph
109 *
110 */
111 int
decode_proceed(Recog * recog)112 decode_proceed(Recog *recog)
113 {
114 MFCCCalc *mfcc;
115 boolean break_flag;
116 boolean break_decode;
117 RecogProcess *p;
118 boolean ok_p;
119 #ifdef GMM_VAD
120 GMMCalc *gmm;
121 boolean break_gmm;
122 #endif
123
124 break_decode = FALSE;
125
126 for(p = recog->process_list; p; p = p->next) {
127 #ifdef DETERMINE
128 p->have_determine = FALSE;
129 #endif
130 p->have_interim = FALSE;
131 }
132 for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
133 mfcc->segmented = FALSE;
134 }
135
136 #ifdef POWER_REJECT
137 for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
138 if (!mfcc->valid) continue;
139 if (mfcc->f == 0) {
140 mfcc->avg_power = 0.0;
141 if (debug2_flag) jlog("STAT: power_reject: reset\n");
142 }
143 }
144 #endif
145
146
147 #ifdef GMM_VAD
148 if (recog->gmm != NULL) {
149 /* reset flags */
150 break_gmm = FALSE;
151 recog->gc->want_rewind = FALSE;
152 }
153 #endif
154 if (recog->gmm != NULL && recog->gmmmfcc->valid) {
155 /* GMM ����Ԥ� */
156 if (recog->gmmmfcc->f == 0) {
157 /* GMM ������ */
158 gmm_prepare(recog);
159 }
160 /* ���Υե졼����Ф���GMM�����٤�� */
161 gmm_proceed(recog);
162 #ifdef GMM_VAD
163 /* Check for GMM-based VAD */
164 gmm = recog->gc;
165 gmm_check_trigger(recog);
166 if (gmm->after_trigger) {
167 /* after trigger, in speech area */
168 if (gmm->down_trigger) {
169 /* down trigger, end segment */
170 #ifdef GMM_VAD_DEBUG
171 printf("GMM_VAD: %d: down trigger\n", recog->gmmmfcc->f);
172 #endif
173 recog->gmmmfcc->sparea_start = recog->gmmmfcc->f + 1 - recog->jconf->detect.gmm_margin;
174 if (recog->gmmmfcc->sparea_start < 0) recog->gmmmfcc->sparea_start = 0;
175 gmm->after_trigger = FALSE;
176 recog->gmmmfcc->segmented = TRUE;
177 break_gmm = TRUE;
178 } else {
179 /* keep recognition */
180 }
181 } else {
182 /* before trigger, in noise area */
183 if (gmm->up_trigger) {
184 /* start recognition */
185 /* request caller to rewind to the backstep point and
186 re-start with normal search */
187 if (recog->gmmmfcc->f + 1 < recog->jconf->detect.gmm_margin) {
188 gmm->rewind_frame = 0;
189 } else {
190 gmm->rewind_frame = recog->gmmmfcc->f + 1 - recog->jconf->detect.gmm_margin;
191 }
192 #ifdef GMM_VAD_DEBUG
193 printf("GMM_VAD: %d: up trigger, start recognition with %d frame rewind\n", recog->gmmmfcc->f, recog->gmmmfcc->f - gmm->rewind_frame);
194 #endif
195 gmm->want_rewind = TRUE;
196 gmm->want_rewind_reprocess = TRUE;
197 gmm->after_trigger = TRUE;
198 return 0;
199 } else {
200 /* before trigger, noise continues */
201
202 /* if noise goes more than a certain frame, shrink the noise area
203 to avoid unlimited memory usage */
204 if (recog->gmmmfcc->f + 1 > GMM_VAD_AUTOSHRINK_LIMIT) {
205 gmm->want_rewind = TRUE;
206 gmm->want_rewind_reprocess = FALSE;
207 gmm->rewind_frame = recog->gmmmfcc->f + 1 - recog->jconf->detect.gmm_margin;
208 if (debug2_flag) {
209 jlog("DEBUG: GMM_VAD: pause exceeded %d, rewind\n", GMM_VAD_AUTOSHRINK_LIMIT);
210 }
211 }
212
213 /* skip recognition processing */
214 return 0;
215 }
216 }
217 #endif /* GMM_VAD */
218 }
219
220 for(p = recog->process_list; p; p = p->next) {
221 if (!p->live) continue;
222 mfcc = p->am->mfcc;
223 if (!mfcc->valid) {
224 /* ���Υե졼��ν������å� */
225 /* skip processing the frame */
226 continue;
227 }
228
229 /* mfcc-f �Υե졼��ˤĤ���ǧ������(�ե졼��Ʊ���ӡ���õ��)��ʤ�� */
230 /* proceed beam search for mfcc->f */
231 if (mfcc->f == 0) {
232 /* �ǽ�Υե졼��: õ������������ */
233 /* initial frame: initialize search process */
234 if (get_back_trellis_init(mfcc->param, p) == FALSE) {
235 jlog("ERROR: %02d %s: failed to initialize the 1st pass\n", p->config->id, p->config->name);
236 return -1;
237 }
238 }
239 if (mfcc->f > 0 || p->am->hmminfo->multipath) {
240 /* 1�ե졼��õ����ʤ�� */
241 /* proceed search for 1 frame */
242 if (get_back_trellis_proceed(mfcc->f, mfcc->param, p, FALSE) == FALSE) {
243 mfcc->segmented = TRUE;
244 break_decode = TRUE;
245 }
246 if (p->config->successive.enabled) {
247 if (detect_end_of_segment(p, mfcc->f - 1)) {
248 /* �������Ƚ�λ����: �裱�ѥ����������� */
249 mfcc->segmented = TRUE;
250 break_decode = TRUE;
251 }
252 }
253 }
254 }
255
256 /* �������Ȥ��٤����ɤ����ǽ�Ū��Ƚ���Ԥ���
257 �ǥ������١���VAD���뤤�� spsegment �ξ�硤ʣ�������֤� OR
258 ���롥�ޤ���GMM�ʤ�ʣ����ब������ϴ��֤� AND ���롥*/
259 /* determine whether to segment at here
260 If multiple segmenter exists, take their AND */
261 break_flag = FALSE;
262 if (break_decode
263 #ifdef GMM_VAD
264 || (recog->gmm != NULL && break_gmm)
265 #endif
266 ) {
267 break_flag = TRUE;
268 }
269
270 if (break_flag) {
271 /* õ�������ν�λ��ȯ�������ΤǤ�����ǧ������.
272 �ǽ�Υե졼�फ�� [f-1] ���ܤޤǤ�ǧ�����줿���Ȥˤʤ�
273 */
274 /* the recognition process tells us to stop recognition, so
275 recognition should be terminated here.
276 the recognized data are [0..f-1] */
277
278 /* �ǽ��ե졼��� last_time �˥��å� */
279 /* set the last frame to last_time */
280 for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
281 mfcc->last_time = mfcc->f - 1;
282 }
283
284 if (! recog->jconf->decodeopt.segment) {
285 /* ���硼�ȥݡ����ʳ����ڤ줿��硤�Ĥ�Υ���ץ��ǧ�������˼ΤƤ� */
286 /* drop rest inputs if segmented by error */
287 for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
288 mfcc->param->header.samplenum = mfcc->f;
289 mfcc->param->samplenum = mfcc->f;
290 }
291 }
292
293 return 1;
294 }
295
296 /* call frame-wise callback for the processing results if any */
297 #ifdef DETERMINE
298 ok_p = FALSE;
299 for(p=recog->process_list;p;p=p->next) {
300 if (!p->live) continue;
301 if (p->have_determine) {
302 ok_p = TRUE;
303 }
304 }
305 if (ok_p) callback_exec(CALLBACK_RESULT_PASS1_DETERMINED, recog);
306 #endif
307 ok_p = FALSE;
308 for(p=recog->process_list;p;p=p->next) {
309 if (!p->live) continue;
310 if (p->have_interim) {
311 ok_p = TRUE;
312 }
313 }
314 if (ok_p) callback_exec(CALLBACK_RESULT_PASS1_INTERIM, recog);
315
316 return 0;
317 }
318
319 #ifdef POWER_REJECT
320 boolean
power_reject(Recog * recog)321 power_reject(Recog *recog)
322 {
323 MFCCCalc *mfcc;
324
325 for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
326 /* skip if not realtime and raw file processing */
327 if (mfcc->avg_power == 0.0) continue;
328 if (debug2_flag) jlog("STAT: power_reject: MFCC%02d: avg_power = %f\n", mfcc->id, mfcc->avg_power / mfcc->param->samplenum);
329 if (mfcc->avg_power / mfcc->param->samplenum < recog->jconf->reject.powerthres) return TRUE;
330 }
331 return FALSE;
332 }
333 #endif
334
335 /**
336 * <EN>
337 * @brief End procedure of the first pass (when segmented)
338 *
339 * This function do things for ending the first pass and prepare for
340 * the next recognition, when the input was segmented at the middle of
341 * recognition by some reason.
342 *
343 * First, the best path at each recognition process instance will be parsed
344 * and stored. In case of recognition error or input rejection, the error
345 * status will be set.
346 *
347 * Then, the last pause segment of the processed input will be cut and saved
348 * to be processed at first in the recognition of the next or remaining input.
349 *
350 * </EN>
351 * <JA>
352 * @brief ��1�ѥ��ν�λ�����ʥ������Ȼ���
353 *
354 * ���Ϥ����餫�λ�ͳ�ˤ�ä�����ǥ������Ȥ��줿���ˡ���1�ѥ���ǧ��������
355 * ��λ���Ƽ���Ƴ����뤿��ν�����Ԥ�.
356 *
357 * �ޤ�����ǧ�������������Ф��ơ�����ñ�������դ�����1�ѥ���
358 * ǧ����̤Ȥ��Ƴ�Ǽ����. �ޤ���ǧ�����ԡ����ϴ��Ѥλ��ϥ��顼���ơ�������
359 * �줾�쥻�åȤ���.
360 *
361 * �����ơ������ǧ���ǡ����Υ������Ȥ�ǧ�����Ф��줿��������
362 * ��֤���Ƴ����뤿��ˡ���������������֤��ڤ�Ф��Ƥ���������Ƥ�.
363 *
364 * </JA>
365 *
366 * @param recog [in] engine instance
367 *
368 * @callgraph
369 * @callergraph
370 */
371 void
decode_end_segmented(Recog * recog)372 decode_end_segmented(Recog *recog)
373 {
374 boolean ok_p;
375 int mseclen;
376 RecogProcess *p;
377 int last_status;
378
379 /* rejectshort �����, ���Ϥ�û����Ф�������1�ѥ���̤���Ϥ��ʤ� */
380 /* suppress 1st pass output if -rejectshort and input shorter than specified */
381 ok_p = TRUE;
382 if (recog->jconf->reject.rejectshortlen > 0) {
383 mseclen = (float)recog->mfcclist->last_time * (float)recog->jconf->input.period * (float)recog->jconf->input.frameshift / 10000.0;
384 if (mseclen < recog->jconf->reject.rejectshortlen) {
385 last_status = J_RESULT_STATUS_REJECT_SHORT;
386 ok_p = FALSE;
387 }
388 }
389
390 #ifdef POWER_REJECT
391 if (ok_p) {
392 if (power_reject(recog)) {
393 last_status = J_RESULT_STATUS_REJECT_POWER;
394 ok_p = FALSE;
395 }
396 }
397 #endif
398
399 if (ok_p) {
400 for(p=recog->process_list;p;p=p->next) {
401 if (!p->live) continue;
402 finalize_1st_pass(p, p->am->mfcc->last_time);
403 }
404 } else {
405 for(p=recog->process_list;p;p=p->next) {
406 if (!p->live) continue;
407 p->result.status = last_status;
408 }
409 }
410 if (recog->jconf->decodeopt.segment) {
411 finalize_segment(recog);
412 }
413
414 if (recog->gmm != NULL) {
415 /* GMM ���ν�λ */
416 gmm_end(recog);
417 }
418 }
419
420 /**
421 * <EN>
422 * @brief End procedure of the first pass
423 *
424 * This function finish the first pass, when the input was fully
425 * processed to the end.
426 *
427 * The best path at each recognition process instance will be parsed
428 * and stored. In case of recognition error or input rejection, the
429 * error status will be set.
430 *
431 * </EN>
432 * <JA>
433 * @brief ��1�ѥ��ν�λ����
434 *
435 * ���Ϥ��Ǹ�ޤǽ�������ƽ�λ�����Ȥ��ˡ���1�ѥ���ǧ��������
436 * �������.
437 *
438 * ��ǧ�������������Ф��ơ����λ����Ǥ���1�ѥ��κ���ñ��
439 * ������Ǽ����. �ޤ���ǧ�����ԡ����ϴ��Ѥλ��ϥ��顼���ơ�������
440 * �줾�쥻�åȤ���.
441 *
442 * </JA>
443 *
444 * @param recog [in] engine instance
445 *
446 * @callgraph
447 * @callergraph
448 */
449 void
decode_end(Recog * recog)450 decode_end(Recog *recog)
451 {
452 MFCCCalc *mfcc;
453 int mseclen;
454 boolean ok_p;
455 RecogProcess *p;
456 int last_status;
457
458 for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
459 mfcc->segmented = FALSE;
460 }
461
462 if (recog->gmm != NULL) {
463 /* GMM ���ν�λ */
464 gmm_end(recog);
465 }
466
467 #ifdef GMM_VAD
468 /* �⤷�ȥꥬ��������ʤ��ޤ����Ͻ�λ��ã�����Τʤ顤���Τޤޥ��顼��λ */
469 if (recog->jconf->decodeopt.segment) {
470 if (recog->gmm) {
471 if (recog->gc->after_trigger == FALSE) {
472 for(p=recog->process_list;p;p=p->next) {
473 p->result.status = J_RESULT_STATUS_ONLY_SILENCE; /* reject by decoding */
474 }
475 /* ���硼�ȥݡ����������ơ������ξ��,
476 ���ϥѥ���ʬ��ʤɤκǽ�������Ԥʤ� */
477 /* When short-pause segmentation enabled */
478 finalize_segment(recog);
479 return;
480 }
481 }
482 }
483 #endif
484
485 /* �裱�ѥ��κǸ�Υե졼���ǧ��������Ԥ� */
486 /* finalize 1st pass */
487 for(p=recog->process_list;p;p=p->next) {
488 if (!p->live) continue;
489 #ifdef SPSEGMENT_NAIST
490 if (recog->jconf->decodeopt.segment) {
491 if (p->pass1.after_trigger == FALSE) continue;
492 }
493 #endif
494 mfcc = p->am->mfcc;
495 if (mfcc->f > 0) {
496 get_back_trellis_end(mfcc->param, p);
497 }
498 }
499
500 /* ����� */
501 for(p=recog->process_list;p;p=p->next) {
502 if (!p->live) continue;
503
504 ok_p = TRUE;
505
506 /* check rejection by no input */
507 if (ok_p) {
508 mfcc = p->am->mfcc;
509 /* ����Ĺ���ǥ륿�η��˽�ʬ�Ǥʤ���硤����̵���Ȥ��롥 */
510 /* if input is short for compute all the delta coeff., terminate here */
511 if (mfcc->f == 0) {
512 jlog("STAT: no input frame\n");
513 last_status = J_RESULT_STATUS_FAIL;
514 ok_p = FALSE;
515 }
516 }
517
518 /* check rejection by input length */
519 if (ok_p) {
520 if (recog->jconf->reject.rejectshortlen > 0) {
521 mseclen = (float)mfcc->param->samplenum * (float)recog->jconf->input.period * (float)recog->jconf->input.frameshift / 10000.0;
522 if (mseclen < recog->jconf->reject.rejectshortlen) {
523 last_status = J_RESULT_STATUS_REJECT_SHORT;
524 ok_p = FALSE;
525 }
526 }
527 }
528
529 #ifdef POWER_REJECT
530 /* check rejection by average power */
531 if (ok_p) {
532 if (power_reject(recog)) {
533 last_status = J_RESULT_STATUS_REJECT_POWER;
534 ok_p = FALSE;
535 }
536 }
537 #endif
538
539 #ifdef SPSEGMENT_NAIST
540 /* check rejection non-triggered input segment */
541 if (ok_p) {
542 if (recog->jconf->decodeopt.segment) {
543 if (p->pass1.after_trigger == FALSE) {
544 last_status = J_RESULT_STATUS_ONLY_SILENCE; /* reject by decoding */
545 ok_p = FALSE;
546 }
547 }
548 }
549 #endif
550
551 if (ok_p) {
552 /* valid input segment, finalize it */
553 finalize_1st_pass(p, mfcc->param->samplenum);
554 } else {
555 /* invalid input segment */
556 p->result.status = last_status;
557 }
558 }
559 if (recog->jconf->decodeopt.segment) {
560 /* ���硼�ȥݡ����������ơ������ξ��,
561 ���ϥѥ���ʬ��ʤɤκǽ�������Ԥʤ� */
562 /* When short-pause segmentation enabled */
563 finalize_segment(recog);
564 }
565 }
566
567
568 /**
569 * <JA>
570 * @brief �ե졼��Ʊ���ӡ���õ���ᥤ��ؿ��ʥХå������ѡ�
571 *
572 * Ϳ����줿���ϥ٥��ȥ�����Ф����裱�ѥ�(�ե졼��Ʊ���ӡ���õ��)��
573 * �Ԥ������η�̤���Ϥ���. �ޤ����ե졼����Ϥ�ñ�콪ü���裲�ѥ�
574 * �Τ����ñ��ȥ�ꥹ��¤�Τ˳�Ǽ����.
575 *
576 * ���δؿ������ϥ٥��ȥ����餫���������Ƥ�������Ѥ�����.
577 * �裱�ѥ������Ϥ����Ƽ¹Ԥ���륪��饤��ǧ���ξ�硤
578 * ���δؿ����Ѥ���줺������ˤ��Υե�������������Ƥ���ƥ��ִؿ���
579 * ľ�� realtime-1stpass.c �⤫��ƤФ��.
580 *
581 * @param recog [in] ������
582 * </JA>
583 * <EN>
584 * @brief Frame synchronous beam search: the main (for batch mode)
585 *
586 * This function perform the 1st recognition pass of frame-synchronous beam
587 * search and output the result. It also stores all the word ends in every
588 * input frame to word trellis structure.
589 *
590 * This function will be called if the whole input vector is already given
591 * to the end. When online recognition, where the 1st pass will be
592 * processed in parallel with input, this function will not be used.
593 * In that case, functions defined in this file will be directly called
594 * from functions in realtime-1stpass.c.
595 *
596 * @param recog [in] engine instance
597 * </EN>
598 * @callgraph
599 * @callergraph
600 */
601 boolean
get_back_trellis(Recog * recog)602 get_back_trellis(Recog *recog)
603 {
604 boolean ok_p;
605 MFCCCalc *mfcc;
606 int rewind_frame;
607 PROCESS_AM *am;
608 boolean reprocess;
609
610 /* initialize mfcc instances */
611 for(mfcc=recog->mfcclist;mfcc;mfcc=mfcc->next) {
612 /* mark all as valid, since all frames are fully prepared beforehand */
613 if (mfcc->param->samplenum == 0) mfcc->valid = FALSE;
614 else mfcc->valid = TRUE;
615 /* set frame pointers to 0 */
616 mfcc->f = 0;
617 }
618
619 /* callback of process start */
620 #ifdef BACKEND_VAD
621 if (recog->jconf->decodeopt.segment) {
622 /* at first time, recognition does not start yet */
623 /* reset segmentation flags */
624 spsegment_init(recog);
625 } else {
626 /* execute callback for pass1 begin here */
627 callback_exec(CALLBACK_EVENT_RECOGNITION_BEGIN, recog);
628 callback_exec(CALLBACK_EVENT_PASS1_BEGIN, recog);
629 recog->triggered = TRUE;
630 }
631 #else
632 if (recog->jconf->decodeopt.segment) {
633 if (!recog->process_segment) {
634 callback_exec(CALLBACK_EVENT_RECOGNITION_BEGIN, recog);
635 }
636 callback_exec(CALLBACK_EVENT_SEGMENT_BEGIN, recog);
637 } else {
638 callback_exec(CALLBACK_EVENT_RECOGNITION_BEGIN, recog);
639 }
640 callback_exec(CALLBACK_EVENT_PASS1_BEGIN, recog);
641 recog->triggered = TRUE;
642 #endif
643
644 while(1) {
645 ok_p = TRUE;
646 for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
647 if (! mfcc->valid) continue;
648 if (mfcc->f < mfcc->param->samplenum) {
649 mfcc->valid = TRUE;
650 ok_p = FALSE;
651 } else {
652 mfcc->valid = FALSE;
653 }
654 }
655 if (ok_p) {
656 /* ���٤Ƥ� MFCC ��������ã�����Τǥ롼��λ */
657 /* all MFCC has been processed, end of loop */
658 break;
659 }
660
661 switch (decode_proceed(recog)) {
662 case -1: /* error */
663 return FALSE;
664 break;
665 case 0: /* success */
666 break;
667 case 1: /* segmented */
668 /* õ������: �������줿���Ϥ� 0 ���� t-2 �ޤ� */
669 /* search terminated: processed input = [0..t-2] */
670 /* ���λ�������1�ѥ���λ���� */
671 /* end the 1st pass at this point */
672 decode_end_segmented(recog);
673 /* terminate 1st pass here */
674 return TRUE;
675 }
676
677 #ifdef BACKEND_VAD
678 /* check up trigger in case of VAD segmentation */
679 if (recog->jconf->decodeopt.segment) {
680 if (recog->triggered == FALSE) {
681 if (spsegment_trigger_sync(recog)) {
682 if (!recog->process_segment) {
683 callback_exec(CALLBACK_EVENT_RECOGNITION_BEGIN, recog);
684 }
685 callback_exec(CALLBACK_EVENT_SEGMENT_BEGIN, recog);
686 callback_exec(CALLBACK_EVENT_PASS1_BEGIN, recog);
687 recog->triggered = TRUE;
688 }
689 }
690 }
691 #endif
692
693 if (spsegment_need_restart(recog, &rewind_frame, &reprocess) == TRUE) {
694 /* do rewind for all mfcc here */
695 spsegment_restart_mfccs(recog, rewind_frame, reprocess);
696 /* reset outprob cache for all AM */
697 for(am=recog->amlist;am;am=am->next) {
698 outprob_prepare(&(am->hmmwrk), am->mfcc->param->samplenum);
699 }
700 }
701 /* call frame-wise callback */
702 callback_exec(CALLBACK_EVENT_PASS1_FRAME, recog);
703
704 /* 1�ե졼��������ʤ���Τǥݥ���ʤ�� */
705 /* proceed frame pointer */
706 for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
707 if (!mfcc->valid) continue;
708 mfcc->f++;
709 }
710
711 if (recog->process_want_terminate) {
712 /* termination requested */
713 decode_end_segmented(recog);
714 return TRUE;
715 }
716 }
717
718 /* �ǽ��ե졼�������Ԥ���ǧ���η�̽��ϤȽ�λ������Ԥ� */
719 decode_end(recog);
720
721 return TRUE;
722 }
723
724 /* end of file */
725