julius/realtime-1stpass.c

Go to the documentation of this file.
00001 
00116 /*
00117  * Copyright (c) 1991-2006 Kawahara Lab., Kyoto University
00118  * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
00119  * Copyright (c) 2005-2006 Julius project team, Nagoya Institute of Technology
00120  * All rights reserved
00121  */
00122 
00123 #include <julius.h>
00124 
00125 #undef RDEBUG                   
00126 
00127 /* input parameter */
00128 static HTK_Param *param = NULL; 
00129 static float *bf;               
00130 static DeltaBuf *db;            
00131 static DeltaBuf *ab;            
00132 static VECT *tmpmfcc;           
00133 static int maxframelen;         
00134 static int last_time;           
00135 
00136 static boolean last_is_segmented; 
00137 #ifdef SP_BREAK_CURRENT_FRAME
00138 static SP16 *rest_Speech = NULL; 
00139 static int rest_alloc_len = 0;  
00140 static int rest_len;            
00141 #endif
00142 
00143 static int f_raw;               
00144 static int f;                   
00145 static SP16 *window;            
00146 static int windowlen;           
00147 static int windownum;           
00148 
00149 /* 計算結果の MFCC を保存する param 構造体を準備する
00150    これは1回の認識ごとに繰り返し呼ばれる */
00151 /* prepare new parameter vector holder for RealTime*
00152    This will be called each time a recognition begins */
00164 static void
00165 init_param()
00166 {
00167   /* param 構造体を新たにアロケート */
00168   /* allocate parameter data */
00169   param = new_param();
00170   /* これから計算されるパラメータの型をヘッダに設定 */
00171   /* set header types */
00172   param->header.samptype = F_MFCC;
00173   if (para.delta) param->header.samptype |= F_DELTA;
00174   if (para.acc) param->header.samptype |= F_ACCL;
00175   if (para.energy) param->header.samptype |= F_ENERGY;
00176   if (para.c0) param->header.samptype |= F_ZEROTH;
00177   if (para.absesup) param->header.samptype |= F_ENERGY_SUP;
00178   if (para.cmn) param->header.samptype |= F_CEPNORM;
00179 
00180   param->header.wshift = para.smp_period * para.frameshift;
00181   param->header.sampsize = para.veclen * sizeof(VECT); /* not compressed */
00182   param->veclen = para.veclen;
00183   /* フレームごとのパラメータベクトル保存のためのヘッダ領域を確保 */
00184   /* 最大時間分を固定でアロケート */
00185   /* assign max (safe with free_param)*/
00186   param->parvec = (VECT **)mymalloc(sizeof(VECT *) * maxframelen);
00187   /* 認識処理中/終了後にセットされる変数:
00188      param->parvec (パラメータベクトル系列)
00189      param->header.samplenum, param->samplenum (全フレーム数)
00190   */
00191   /* variables that will be set while/after computation has been done:
00192      param->parvec (parameter vector sequence)
00193      param->header.samplenum, param->samplenum (total number of frames)
00194   */
00195 }
00196 
00206 void
00207 RealTimeInit()
00208 {
00209   /* -ssload 指定時, SS用のノイズスペクトルをファイルから読み込む */
00210   /* if "-ssload", load noise spectrum for spectral subtraction from file */
00211   if (ssload_filename && ssbuf == NULL) {
00212     if ((ssbuf = new_SS_load_from_file(ssload_filename, &sslen)) == NULL) {
00213       j_error("Error: failed to read \"%s\"\n", ssload_filename);
00214     }
00215   }
00216   /* MFCC計算関数を初期化 */
00217   /* initialize MFCC computation functions */
00218   WMP_init(para, &bf, ssbuf, sslen);
00219   /* 対数エネルギー正規化のための初期値 */
00220   /* set initial value for log energy normalization */
00221   if (para.energy && para.enormal) energy_max_init();
00222   /* デルタ計算のためのサイクルバッファを用意 */
00223   /* initialize cycle buffers for delta and accel coef. computation */
00224   if (para.delta) db = WMP_deltabuf_new(para.baselen, para.delWin);
00225   if (para.acc) ab = WMP_deltabuf_new(para.baselen * 2, para.accWin);
00226   /* デルタ計算のためのワークエリアを確保 */
00227   /* allocate work area for the delta computation */
00228   tmpmfcc = (VECT *)mymalloc(sizeof(VECT) * para.vecbuflen);
00229   /* 最大フレーム長を最大入力時間数から計算 */
00230   /* set maximum allowed frame length */
00231   maxframelen = MAXSPEECHLEN / para.frameshift;
00232   /* 窓長をセット */
00233   /* set window length */
00234   windowlen = para.framesize + 1;
00235   /* 窓かけ用バッファを確保 */
00236   /* set window buffer */
00237   window = mymalloc(sizeof(SP16) * windowlen);
00238   /* MAP-CMN 用の初期ケプストラム平均を読み込んで初期化する */
00239   /* Initialize the initial cepstral mean data from file for MAP-CMN */
00240   if (para.cmn) CMN_realtime_init(para.mfcc_dim, cmn_map_weight);
00241   /* -cmnload 指定時, CMN用のケプストラム平均の初期値をファイルから読み込む */
00242   /* if "-cmnload", load initial cepstral mean data from file for CMN */
00243   if (cmnload_filename) {
00244     if (para.cmn) {
00245       if ((cmn_loaded = CMN_load_from_file(cmnload_filename, para.mfcc_dim))== FALSE) {
00246         j_printf("Warning: failed to read cepstral mean from \"%s\"\n", cmnload_filename);
00247       }
00248     } else {
00249       j_printf("Warning: CMN not required, file \"%s\" ignored\n", cmnload_filename);
00250     }
00251   }
00252 }
00253 
00254 /* ON-THE-FLY デコーディング関数: 準備 (認識開始時ごとに呼ばれる) */
00255 /* ON-THE-FLY DECODING FUNCTION: prepare (on start of every input segment) */
00265 void
00266 RealTimePipeLinePrepare()
00267 {
00268   /* 計算結果の MFCC を保存する param 構造体を準備する */
00269   /* prepare param to hold the resulting MFCC parameters */
00270   init_param();
00271   /* 対数エネルギー正規化のための初期値をセット */
00272   /* set initial value for log energy normalization */
00273   if (para.energy && para.enormal) energy_max_prepare(&para);
00274   /* デルタ計算用バッファを準備 */
00275   /* set the delta cycle buffer */
00276   if (para.delta) WMP_deltabuf_prepare(db);
00277   if (para.acc) WMP_deltabuf_prepare(ab);
00278   /* 音響尤度計算用キャッシュを準備
00279      最大長をここであらかじめ確保してしまう */
00280   /* prepare cache area for acoustic computation of HMM states and mixtures
00281      pre-fetch for maximum length here */
00282   outprob_prepare(maxframelen);
00283   /* 準備した param 構造体のデータのパラメータ型を音響モデルとチェックする */
00284   /* check type coherence between param and hmminfo here */
00285   if (!check_param_coherence(hmminfo, param)) {
00286     j_error("parameter type not match?\n");
00287   }
00288   /* 計算用の変数を初期化 */
00289   /* initialize variables for computation */
00290   f_raw = 0;
00291   f = 0;
00292   windownum = 0;
00293 
00294   /* MAP-CMN の初期化 */
00295   /* Prepare for MAP-CMN */
00296   if (para.cmn) CMN_realtime_prepare();
00297 
00298   /* -record 指定時, 音声データを保存するファイルをここで開く */
00299   /* if "-record", open the file to write the incoming speech data here */
00300   if (record_dirname != NULL) {
00301     record_sample_open();
00302   }
00303   
00304 #ifdef VISUALIZE
00305   /* 音声波形の画面出力用に, 音声データを別に保存する.
00306      ここではポインタを初期化するのみ   */
00307   /* record data for waveform printing */
00308   speechlen = 0;
00309 #endif
00310 }
00311 
00350 int
00351 RealTimePipeLine(SP16 *Speech, int nowlen) /* Speech[0...nowlen] = input */
00352 {
00353   int i, now;
00354   boolean ret;
00355   LOGPROB f;
00356 
00357   /* window[0..windownum-1] は前回の呼び出しで残った音声データが格納されている */
00358   /* window[0..windownum-1] are speech data left from previous call */
00359 
00360   /* 処理用ポインタを初期化 */
00361   /* initialize pointer for local processing */
00362   now = 0;
00363   
00364   /* 認識処理がセグメント要求で終わったのかどうかのフラグをリセット */
00365   /* reset flag which indicates whether the input has ended with segmentation request */
00366   last_is_segmented = FALSE;
00367 
00368   /* 初めて呼び出されたときに, 認識開始のメッセージを出力 */
00369   /* If this is the first call, output start recording/processing message */
00370   if (f_raw == 0) status_recstart();
00371 
00372 #ifdef RDEBUG
00373   printf("got %d samples\n", nowlen);
00374 #endif
00375 
00376   /* -record 時, 音声データをファイルに追加する */
00377   /* if "-record", append the incoming samples to a file */
00378   if (record_dirname != NULL) {
00379     record_sample_write(Speech, nowlen);
00380   }
00381 
00382 #ifdef VISUALIZE
00383   /* record data for waveform printing */
00384   adin_cut_callback_store_buffer(Speech, nowlen);
00385 #endif
00386 
00387   while (now < nowlen) {        /* till whole input is processed */
00388     /* 入力長が maxframelen に達したらここで強制終了 */
00389     /* if input length reaches maximum buffer size, terminate 1st pass here */
00390     if (f_raw >= maxframelen) return(1);
00391     /* 窓バッファを埋められるだけ埋める */
00392     /* fill window buffer as many as possible */
00393     for(i = min(windowlen - windownum, nowlen - now); i > 0 ; i--)
00394       window[windownum++] = (float) Speech[now++];
00395     /* もし窓バッファが埋まらなければ, このセグメントの処理はここで終わる.
00396        処理されなかったサンプル (window[0..windownum-1]) は次回に持ち越し.*/
00397     /* if window buffer was not filled, end processing here, keeping the
00398        rest samples (window[0..windownum-1]) in the window buffer. */
00399     if (windownum < windowlen) break;
00400 #ifdef RDEBUG
00401     /*    printf("%d used, %d rest\n", now, nowlen - now);
00402 
00403           printf("[f_raw = %d, f = %d]\n", f_raw, f);*/
00404 #endif
00405 
00406     /* 音声波形から base MFCC を計算 */
00407     /* calculate base MFCC from waveform */
00408     for (i=0; i < windowlen; i++) {
00409       bf[i+1] = (float) window[i];
00410     }
00411     WMP_calc(tmpmfcc, bf, para, ssbuf);
00412 
00413     if (para.energy && para.enormal) {
00414       /* 対数エネルギー項を正規化する */
00415       /* normalize log energy */
00416       /* リアルタイム入力では発話ごとの最大エネルギーが得られないので
00417          直前の発話のパワーで代用する */
00418       /* Since the maximum power of the whole input utterance cannot be
00419          obtained at real-time input, the maximum of last input will be
00420          used to normalize.
00421       */
00422       tmpmfcc[para.baselen-1] = energy_max_normalize(tmpmfcc[para.baselen-1], &para);
00423     }
00424 
00425     if (para.delta) {
00426       /* デルタを計算する */
00427       /* calc delta coefficients */
00428       ret = WMP_deltabuf_proceed(db, tmpmfcc);
00429 #ifdef RDEBUG
00430       printf("DeltaBuf: ret=%d, status=", ret);
00431       for(i=0;i<db->len;i++) {
00432         printf("%d", db->is_on[i]);
00433       }
00434       printf(", nextstore=%d\n", db->store);
00435 #endif
00436       /* ret == FALSE のときはまだディレイ中なので認識処理せず次入力へ */
00437       /* if ret == FALSE, there is no available frame.  So just wait for
00438          next input */
00439       if (! ret) {
00440         goto next_input;
00441       }
00442       /* db->vec に現在の元データとデルタ係数が入っているので tmpmfcc にコピー */
00443       /* now db->vec holds the current base and full delta, so copy them to tmpmfcc */
00444       memcpy(tmpmfcc, db->vec, sizeof(VECT) * para.baselen * 2);
00445     }
00446 
00447     if (para.acc) {
00448       /* Accelerationを計算する */
00449       /* calc acceleration coefficients */
00450       /* base+delta をそのまま入れる */
00451       /* send the whole base+delta to the cycle buffer */
00452       ret = WMP_deltabuf_proceed(ab, tmpmfcc);
00453 #ifdef RDEBUG
00454       printf("AccelBuf: ret=%d, status=", ret);
00455       for(i=0;i<ab->len;i++) {
00456         printf("%d", ab->is_on[i]);
00457       }
00458       printf(", nextstore=%d\n", ab->store);
00459 #endif
00460       /* ret == FALSE のときはまだディレイ中なので認識処理せず次入力へ */
00461       /* if ret == FALSE, there is no available frame.  So just wait for
00462          next input */
00463       if (! ret) {
00464         goto next_input;
00465       }
00466       /* ab->vec には,(base+delta) とその差分係数が入っている.
00467          [base] [delta] [delta] [acc] の順で入っているので,
00468          [base] [delta] [acc] を tmpmfcc にコピーする.*/
00469       /* now ab->vec holds the current (base+delta) and their delta coef. 
00470          it holds a vector in the order of [base] [delta] [delta] [acc], 
00471          so copy the [base], [delta] and [acc] to tmpmfcc.  */
00472       memcpy(tmpmfcc, ab->vec, sizeof(VECT) * para.baselen * 2);
00473       memcpy(&(tmpmfcc[para.baselen*2]), &(ab->vec[para.baselen*3]), sizeof(VECT) * para.baselen);
00474     }
00475 
00476     if (para.delta && (para.energy || para.c0) && para.absesup) {
00477       /* 絶対値パワーを除去 */
00478       /* suppress absolute power */
00479       memmove(&(tmpmfcc[para.baselen-1]), &(tmpmfcc[para.baselen]), sizeof(VECT) * (para.vecbuflen - para.baselen));
00480     }
00481 
00482     /* この時点で tmpmfcc に現時点での最新の特徴ベクトルが格納されている */
00483     /* tmpmfcc[] now holds the latest parameter vector */
00484 
00485 #ifdef RDEBUG
00486       printf("DeltaBuf: got frame %d\n", f_raw);
00487 #endif
00488       /* CMN を計算 */
00489       /* perform CMN */
00490       if (para.cmn) CMN_realtime(tmpmfcc, para.mfcc_dim);
00491 
00492       /* MFCC完成,登録 */
00493       /* now get the MFCC vector of current frame, now store it to param */
00494       param->parvec[f_raw] = (VECT *)mymalloc(sizeof(VECT) * param->veclen);
00495       memcpy(param->parvec[f_raw], tmpmfcc, sizeof(VECT) * param->veclen);
00496       f = f_raw;
00497 
00498       /* ここでフレーム "f" に最新のMFCCが保存されたことになる */
00499       /* now we got the most recent MFCC parameter for frame 'f' */
00500       /* この "f" のフレームについて認識処理(フレーム同期ビーム探索)を進める */
00501       /* proceed beam search for this frame [f] */
00502       if (f == 0) {
00503         /* 最初のフレーム: 探索処理を初期化 */
00504         /* initial frame: initialize search process */
00505         get_back_trellis_init(param, wchmm, &backtrellis);
00506       }
00507 #ifndef MULTIPATH_VERSION
00508       if (f != 0) {
00509 #endif
00510         /* 1フレーム探索を進める */
00511         /* proceed search for 1 frame */
00512         if (get_back_trellis_proceed(f, param, wchmm, &backtrellis
00513 #ifdef MULTIPATH_VERSION
00514                                      ,FALSE
00515 #endif
00516                                      ) == FALSE) {
00517           /* 探索処理の終了が発生したのでここで認識を終える.
00518              最初のフレームから [f-1] 番目までが認識されたことになる
00519           */
00520           /* the recognition process tells us to stop recognition, so
00521              recognition should be terminated here.
00522              the recognized data are [0..f-1] */
00523           /* 認識処理は f-1 で終わったが, MFCCの計算は f まで,初期のMFCC計算
00524              は f_raw まで進んでいることに注意: 後で再開処理が必要*/
00525           /* notice: recognition process has done for "f-1" frame, but MFCC
00526              computation has already done for "f", and first 12-dim. MFCC
00527              has been alsp computed till "f_raw".  Some restarting operation
00528              is needed later */
00529 
00530           /* 認識処理のセグメント要求で終わったことをフラグにセット */
00531           /* set flag which indicates that the input has ended with segmentation request */
00532           last_is_segmented = TRUE;
00533           /* 最終フレームを last_time にセット */
00534           /* set the last frame to last_time */
00535           last_time = f-1;
00536 #ifdef SP_BREAK_CURRENT_FRAME
00537           /* ショートポーズセグメンテーション: バッファに残っているデータを
00538              別に保持して,次回の最初に処理する */
00539           /* short pause segmentation: there is some data left in buffer, so
00540            we should keep them for next processing */
00541           param->header.samplenum = f_raw+1;/* len = lastid + 1 */
00542           param->samplenum = f_raw+1;
00543           rest_len = nowlen - now;
00544           if (rest_len > 0) {
00545             /* copy rest samples to rest_Speech */
00546             if (rest_Speech == NULL) {
00547               rest_alloc_len = rest_len;
00548               rest_Speech = (SP16 *)mymalloc(sizeof(SP16)*rest_alloc_len);
00549             } else if (rest_alloc_len < rest_len) {
00550               rest_alloc_len = rest_len;
00551               rest_Speech = (SP16 *)myrealloc(rest_Speech, sizeof(SP16)*rest_alloc_len);
00552             }
00553             memcpy(rest_Speech, &(Speech[now]), sizeof(SP16) * rest_len);
00554           }
00555 #else
00556           /* param に格納されたフレーム長をセット */
00557           /* set number of frames to param */
00558           param->header.samplenum = f;
00559           param->samplenum = f;
00560 #endif
00561           /* tell the caller to be segmented by this function */
00562           /* 呼び出し元に,ここで入力を切るよう伝える */
00563           return(1);
00564         }
00565 #ifndef MULTIPATH_VERSION
00566       }
00567 #endif
00568       /* 1フレーム処理が進んだのでポインタを進める */
00569       /* proceed frame pointer */
00570       f_raw++;
00571 
00572   next_input:
00573 
00574     /* 窓バッファを処理が終わった分シフト */
00575     /* shift window */
00576     memmove(window, &(window[para.frameshift]), sizeof(SP16) * (windowlen - para.frameshift));
00577     windownum -= para.frameshift;
00578   }
00579 
00580   /* 与えられた音声セグメントに対する認識処理が全て終了
00581      呼び出し元に, 入力を続けるよう伝える */
00582   /* input segment is fully processed
00583      tell the caller to continue input */
00584   return(0);                    
00585 }
00586 
00587 #ifdef SP_BREAK_CURRENT_FRAME
00588 
00622 int
00623 RealTimeResume()
00624 {
00625   int t;
00626 
00627   /* rest_param に最後のsp区間のパラメータが入っている */
00628   /* rest_param holds the last MFCC parameters */
00629   param = rest_param;
00630 
00631   /* paramを準備 */
00632   /* prepare param by expanding the last input param */
00633   outprob_prepare(maxframelen);
00634   param->parvec = (VECT **)myrealloc(param->parvec, sizeof(VECT *) * maxframelen);
00635   /* param にある全パラメータを処理する: f_raw をあらかじめセット */
00636   /* process all data in param: pre-set the resulting f_raw */
00637   f_raw = param->samplenum - 1;
00638 
00639   /* param 内の全フレームについて認識処理を進める */
00640   /* proceed recognition for all frames in param */
00641   if (f_raw >= 0) {
00642     f = f_raw;
00643 #ifdef RDEBUG
00644     printf("Resume: f=%d,f_raw=%d\n", f, f_raw);
00645 #endif
00646     get_back_trellis_init(param, wchmm, &backtrellis);
00647     for (t=
00648 #ifdef MULTIPATH_VERSION
00649            0
00650 #else
00651            1
00652 #endif
00653            ;t<=f;t++) {
00654       if (get_back_trellis_proceed(t, param, wchmm, &backtrellis
00655 #ifdef MULTIPATH_VERSION
00656                                    ,FALSE
00657 #endif
00658                                    ) == FALSE) {
00659         /* segmented, end procs ([0..f])*/
00660         last_is_segmented = TRUE;
00661         last_time = t-1;
00662         return(1);              /* segmented by this function */
00663       }
00664     }
00665   }
00666 
00667   f_raw++;
00668   f = f_raw;
00669 
00670   /* シフトしておく */
00671   /* do last shift */
00672   memmove(window, &(window[para.frameshift]), sizeof(SP16) * (windowlen - para.frameshift));
00673   windownum -= para.frameshift;
00674 
00675   /* これで再開の準備が整ったので,まずは前回の処理で残っていた音声データから
00676      処理する */
00677   /* now that the search status has been prepared for the next input, we
00678      first process the rest unprocessed samples at the last session */
00679   if (rest_len > 0) {
00680 #ifdef RDEBUG
00681     printf("Resume: rest %d samples\n", rest_len);
00682 #endif
00683     return(RealTimePipeLine(rest_Speech, rest_len));
00684   }
00685 
00686   /* 新規の入力に対して認識処理は続く… */
00687   /* the recognition process will continue for the newly incoming samples... */
00688   return 0;
00689 }
00690 #endif /* SP_BREAK_CURRENT_FRAME */
00691 
00692 
00693 /* ON-THE-FLY デコーディング関数: 終了処理 */
00694 /* ON-THE-FLY DECODING FUNCTION: end processing */
00711 HTK_Param *
00712 RealTimeParam(LOGPROB *backmax)
00713 {
00714   boolean ret1, ret2;
00715 
00716   if (last_is_segmented) {
00717     /* RealTimePipeLine で認識処理側の理由により認識が中断した場合,
00718        現状態のMFCC計算データをそのまま次回へ保持する必要があるので,
00719        MFCC計算終了処理を行わずに第1パスの結果のみ出力して終わる.*/
00720     /* When input segmented by recognition process in RealTimePipeLine(),
00721        we have to keep the whole current status of MFCC computation to the
00722        next call.  So here we only output the 1st pass result. */
00723     *backmax = finalize_1st_pass(&backtrellis, winfo, last_time);
00724 #ifdef SP_BREAK_CURRENT_FRAME
00725     finalize_segment(&backtrellis, param, last_time);
00726 #endif
00727     /* この区間の param データを第2パスのために返す */
00728     /* return obtained parameter for 2nd pass */
00729     return(param);
00730   }
00731 
00732   /* MFCC計算の終了処理を行う: 最後の遅延フレーム分を処理 */
00733   /* finish MFCC computation for the last delayed frames */
00734 
00735   if (para.delta || para.acc) {
00736 
00737     /* look until all data has been flushed */
00738     while(f_raw < maxframelen) {
00739 
00740       /* check if there is data in cycle buffer of delta */
00741       ret1 = WMP_deltabuf_flush(db);
00742 #ifdef RDEBUG
00743       {
00744         int i;
00745         printf("DeltaBufLast: ret=%d, status=", ret1);
00746         for(i=0;i<db->len;i++) {
00747           printf("%d", db->is_on[i]);
00748         }
00749         printf(", nextstore=%d\n", db->store);
00750       }
00751 #endif
00752       if (ret1) {
00753         /* uncomputed delta has flushed, compute it with tmpmfcc */
00754         if (para.energy && para.absesup) {
00755           memcpy(tmpmfcc, db->vec, sizeof(VECT) * (para.baselen - 1));
00756           memcpy(&(tmpmfcc[para.baselen-1]), &(db->vec[para.baselen]), sizeof(VECT) * para.baselen);
00757         } else {
00758           memcpy(tmpmfcc, db->vec, sizeof(VECT) * para.baselen * 2);
00759         }
00760         if (para.acc) {
00761           /* this new delta should be given to the accel cycle buffer */
00762           ret2 = WMP_deltabuf_proceed(ab, tmpmfcc);
00763 #ifdef RDEBUG
00764           printf("AccelBuf: ret=%d, status=", ret2);
00765           for(i=0;i<ab->len;i++) {
00766             printf("%d", ab->is_on[i]);
00767           }
00768           printf(", nextstore=%d\n", ab->store);
00769 #endif
00770           if (ret2) {
00771             /* uncomputed accel was given, compute it with tmpmfcc */
00772             memcpy(tmpmfcc, ab->vec, sizeof(VECT) * (para.veclen - para.baselen));
00773             memcpy(&(tmpmfcc[para.veclen - para.baselen]), &(ab->vec[para.veclen - para.baselen]), sizeof(VECT) * para.baselen);
00774           } else {
00775             /* no input is still available: */
00776             /* in case of very short input: go on to the next input */
00777             continue;
00778           }
00779         }
00780       } else {
00781         /* no data left in the delta buffer */
00782         if (para.acc) {
00783           /* no new data, just flush the accel buffer */
00784           ret2 = WMP_deltabuf_flush(ab);
00785 #ifdef RDEBUG
00786           printf("AccelBuf: ret=%d, status=", ret2);
00787           for(i=0;i<ab->len;i++) {
00788             printf("%d", ab->is_on[i]);
00789           }
00790           printf(", nextstore=%d\n", ab->store);
00791 #endif
00792           if (ret2) {
00793             /* uncomputed data has flushed, compute it with tmpmfcc */
00794             memcpy(tmpmfcc, ab->vec, sizeof(VECT) * (para.veclen - para.baselen));
00795             memcpy(&(tmpmfcc[para.veclen - para.baselen]), &(ab->vec[para.veclen - para.baselen]), sizeof(VECT) * para.baselen);
00796           } else {
00797             /* actually no data exists in both delta and accel */
00798             break;              /* end this loop */
00799           }
00800         } else {
00801           /* only delta: input fully flushed, end this loop */
00802           break;
00803         }
00804       }
00805       if(para.cmn) CMN_realtime(tmpmfcc, para.mfcc_dim);
00806       param->parvec[f_raw] = (VECT *)mymalloc(sizeof(VECT) * param->veclen);
00807       memcpy(param->parvec[f_raw], tmpmfcc, sizeof(VECT) * param->veclen);
00808       f = f_raw;
00809       if (f == 0) {
00810         get_back_trellis_init(param, wchmm, &backtrellis);
00811       }
00812 #ifdef MULTIPATH_VERSION
00813       get_back_trellis_proceed(f, param, wchmm, &backtrellis, FALSE);
00814 #else
00815       if (f != 0) {
00816         get_back_trellis_proceed(f, param, wchmm, &backtrellis);
00817       }
00818 #endif
00819       f_raw++;
00820     }
00821   }
00822 
00823   /* フレーム長をセット */
00824   /* set frame length */
00825   param->header.samplenum = f_raw;
00826   param->samplenum = f_raw;
00827 
00828   /* 入力長がデルタの計算に十分でない場合,
00829      MFCC が CMN まで正しく計算できないため,エラー終了とする.*/
00830   /* if input is short for compute all the delta coeff., terminate here */
00831   if (f_raw == 0) {
00832     j_printf("Error: too short input to compute delta coef! (%d frames)\n", f_raw);
00833     *backmax = finalize_1st_pass(&backtrellis, winfo, param->samplenum);
00834   } else {
00835     /* 第1パスの終了処理を行う */
00836     /* finalize 1st pass */
00837     get_back_trellis_end(param, wchmm, &backtrellis);
00838     *backmax = finalize_1st_pass(&backtrellis, winfo, param->samplenum);
00839 #ifdef SP_BREAK_CURRENT_FRAME
00840     finalize_segment(&backtrellis, param, param->samplenum);
00841 #endif
00842   }
00843 
00844   /* この区間の param データを第2パスのために返す */
00845   /* return obtained parameter for 2nd pass */
00846   return(param);
00847 }
00848 
00861 void
00862 RealTimeCMNUpdate(HTK_Param *param)
00863 {
00864   float mseclen;
00865   boolean cmn_update_p;
00866   
00867   /* update CMN vector for next speech */
00868   if(para.cmn) {
00869     if (cmn_update) {
00870       cmn_update_p = TRUE;
00871       if (rejectshortlen > 0) {
00872         /* not update if rejected by short input */
00873         mseclen = (float)param->samplenum * (float)para.smp_period * (float)para.frameshift / 10000.0;
00874         if (mseclen < rejectshortlen) {
00875           cmn_update_p = FALSE;
00876         }
00877       }
00878       if (gmm_reject_cmn_string != NULL) {
00879         /* if using gmm, try avoiding update of CMN for noise input */
00880         if(! gmm_valid_input()) {
00881           cmn_update_p = FALSE;
00882         }
00883       }
00884       if (cmn_update_p) {
00885         /* update last CMN parameter for next spech */
00886         CMN_realtime_update();
00887       } else {
00888         /* do not update, because the last input is bogus */
00889         j_printf("CMN not updated\n");
00890       }
00891     }
00892     /* if needed, save the updated CMN parameter to a file */
00893     if (cmnsave_filename) {
00894       if (CMN_save_to_file(cmnsave_filename) == FALSE) {
00895         j_printf("Warning: failed to save cmn data to \"%s\"\n", cmnsave_filename);
00896       }
00897     }
00898   }
00899 }
00900 
00909 void
00910 RealTimeTerminate()
00911 {
00912   param->header.samplenum = f_raw;
00913   param->samplenum = f_raw;
00914 
00915   /* 入力長がデルタの計算に十分でない場合,
00916      MFCC が CMN まで正しく計算できないため,エラー終了とする.*/
00917   /* if input is short for compute all the delta coeff., terminate here */
00918   if (f_raw == 0) {
00919     finalize_1st_pass(&backtrellis, winfo, param->samplenum);
00920   } else {
00921     /* 第1パスの終了処理を行う */
00922     /* finalize 1st pass */
00923     status_recend();
00924     get_back_trellis_end(param, wchmm, &backtrellis);
00925     finalize_1st_pass(&backtrellis, winfo, param->samplenum);
00926 #ifdef SP_BREAK_CURRENT_FRAME
00927     finalize_segment(&backtrellis, param, param->samplenum);
00928 #endif
00929   }
00930   /* パラメータを解放 */
00931   /* free parameter */
00932   free_param(param);
00933 }

Generated on Tue Dec 26 12:53:21 2006 for Julian by  doxygen 1.5.0