00001 
00110 
00111 
00112 
00113 
00114 
00115 
00116 
00117 #include <sent/stddefs.h>
00118 #include <sent/speech.h>
00119 #include <sent/adin.h>
00120 #ifdef HAVE_PTHREAD
00121 #include <pthread.h>
00122 #endif
00123 
00125 #undef THREAD_DEBUG
00127 #define TMP_FIX_200602          
00128 
00134 static int c_length  = 5000;    
00135 static int c_offset  = 0;       
00136 static int wstep   = DEFAULT_WSTEP;     
00137 static int thres;               
00138 static int noise_zerocross;     
00139 static int nc_max;              
00140 
00141 
00147 static SP16 *swapbuf;           
00148 static int sbsize, sblen;       
00149 static int rest_tail;           
00150 
00151 
00157 static boolean (*ad_resume)();  
00158 static boolean (*ad_pause)();   
00159 static int (*ad_read)(SP16 *, int); 
00160 static boolean adin_cut_on;     
00161 static boolean silence_cut_default; 
00162 static boolean strip_flag;      
00163 static boolean enable_thread = FALSE;   
00164 static boolean ignore_speech_while_recog = TRUE; 
00165 static boolean need_zmean;      
00166 
00167 
00168 #ifdef HAVE_PTHREAD
00169 static void adin_thread_create(); 
00170 #endif
00171 
00178 void
00179 adin_setup_func(int (*cad_read)(SP16 *, int), 
00180                 boolean (*cad_pause)(), 
00181                 boolean (*cad_resume)(), 
00182                 boolean use_cut_def, 
00183                 boolean need_thread 
00184                 )
00185 {
00186   ad_read = cad_read;
00187   ad_pause = cad_pause;
00188   ad_resume = cad_resume;
00189   silence_cut_default = use_cut_def;
00190 #ifdef HAVE_PTHREAD
00191   enable_thread = need_thread;
00192 #else
00193   if (need_thread == TRUE) {
00194     j_printerr("Warning: thread not supported, input may be corrupted on slow machines\n");
00195   }
00196 #endif
00197 }
00198 
00215 void
00216 adin_setup_param(int silence_cut, boolean strip_zero, int cthres, int czc, int head_margin, int tail_margin, int sample_freq, boolean ignore_speech, boolean need_zeromean)
00217 {
00218   float samples_in_msec;
00219   if (silence_cut < 2) {
00220     adin_cut_on = (silence_cut == 1) ? TRUE : FALSE;
00221   } else {
00222     adin_cut_on = silence_cut_default;
00223   }
00224   strip_flag = strip_zero;
00225   thres = cthres;
00226   ignore_speech_while_recog = ignore_speech;
00227   need_zmean = need_zeromean;
00228   
00229   samples_in_msec = (float) sample_freq / (float)1000.0;
00230   
00231   c_length = (int)((float)head_margin * samples_in_msec);       
00232   
00233   noise_zerocross = czc * c_length / sample_freq;
00234   
00235   wstep = DEFAULT_WSTEP;
00236   
00237   nc_max = (int)((float)(tail_margin * samples_in_msec / (float)wstep)) + 2;
00238   sbsize = tail_margin * samples_in_msec + (c_length * czc / 200);
00239 
00240 #ifdef HAVE_PTHREAD
00241   if (enable_thread) {
00242     
00243     adin_thread_create();
00244   }
00245 #endif
00246 }
00247 
00253 boolean
00254 query_segment_on()
00255 {
00256   return adin_cut_on;
00257 }
00258 
00264 boolean
00265 query_thread_on()
00266 {
00267   return enable_thread;
00268 }
00269 
00274 void
00275 adin_reset_zmean()
00276 {
00277   if (need_zmean) zmean_reset();
00278 }
00279 
00280 
00281 #ifdef HAVE_PTHREAD
00282 
00287 static pthread_t adin_thread;   
00288 static pthread_mutex_t mutex;   
00289 static SP16 *speech;            
00290 static int speechlen;           
00291 
00300 static boolean transfer_online = FALSE; 
00301 static boolean adinthread_buffer_overflowed = FALSE; 
00302 
00303 #endif
00304 
00310 static SP16 *buffer = NULL;     
00311 static int bpmax;               
00312 static int bp;                  
00313 static int current_len;         
00314 static SP16 *cbuf;              
00315 
00316 
00317 
00323 static void
00324 adin_purge(int from)
00325 {
00326   if (from > 0 && current_len-from > 0) {
00327     memmove(buffer, &(buffer[from]), (current_len - from) * sizeof(SP16));
00328   }
00329   bp = current_len - from;
00330 }
00331 
00350 static int
00351 adin_cut(
00352          int (*ad_process)(SP16 *, int), 
00353          int (*ad_check)())     
00354 {
00355   static int i;
00356   static boolean is_valid_data; 
00357   int ad_process_ret;
00358   int imax, len, cnt;
00359   static boolean end_of_stream; 
00360   static int need_init = TRUE;  
00361   static int end_status;        
00362   static boolean transfer_online_local; 
00363   
00364   static int zc;                
00365   static int nc;                
00366 
00367   
00368 
00369 
00370 
00371 
00372 
00373 
00374 
00375 
00376 
00377 
00378 
00379   
00380   
00381   
00382   if (buffer == NULL) {         
00383     buffer = (SP16 *)mymalloc(sizeof(SP16) * MAXSPEECHLEN);
00384     cbuf = (SP16 *)mymalloc(sizeof(SP16) * c_length);
00385     swapbuf = (SP16 *)mymalloc(sizeof(SP16) * sbsize);
00386   }
00387   if (need_init) {
00388     bpmax = MAXSPEECHLEN;
00389     bp = 0;
00390     is_valid_data = FALSE;
00391     
00392     if (adin_cut_on) {
00393       init_count_zc_e(thres, c_length, c_offset);
00394     }
00395     end_of_stream = FALSE;
00396     nc = 0;
00397     sblen = 0;
00398     need_init = FALSE;          
00399   }
00400       
00401   
00402   
00403   
00404   
00405   if (ad_resume != NULL) {
00406     if ((*ad_resume)() == FALSE)  return(-1);
00407   }
00408 
00409   
00410   
00411   
00412   for (;;) {
00413 
00414     
00415     
00416     
00417     if (end_of_stream) {
00418       
00419       current_len = bp;
00420     } else {
00421       
00422       
00423       
00424       
00425       
00426 
00427 
00428 
00429 
00430 
00431 
00432 
00433 
00434 
00435 
00436       cnt = (*ad_read)(&(buffer[bp]), bpmax - bp);
00437       if (cnt < 0) {            
00438         
00439         if (cnt == -2) end_status = -1; 
00440         else if (cnt == -1) end_status = 0; 
00441         
00442 
00443 
00444 
00445         end_of_stream = TRUE;           
00446         cnt = 0;                        
00447         
00448         if (bp == 0) break;
00449       }
00450 
00451       
00452       
00453       
00454       if (cnt > 0) {
00455         if (strip_flag) {
00456           
00457           len = strip_zero(&(buffer[bp]), cnt);
00458           if (len != cnt) cnt = len;
00459         }
00460         if (need_zmean) {
00461           
00462           sub_zmean(&(buffer[bp]), cnt);
00463         }
00464       }
00465       
00466       
00467       current_len = bp + cnt;
00468     }
00469 #ifdef THREAD_DEBUG
00470     if (end_of_stream) {
00471       printf("stream already ended\n");
00472     }
00473     printf("input: get %d samples [%d-%d]\n", current_len - bp, bp, current_len);
00474 #endif
00475 
00476     
00477     
00478     
00479     
00480 
00481     
00482     if (ad_check != NULL
00483 #ifdef HAVE_PTHREAD
00484         && !enable_thread
00485 #endif
00486         ) {
00487       
00488       if ((i = (*ad_check)()) < 0) { 
00489         
00490         if (i == -2 ||
00491             (i == -1 && adin_cut_on && is_valid_data == FALSE) ||
00492             (i == -1 && !adin_cut_on && current_len == 0)) {
00493           end_status = -2;      
00494           goto break_input;
00495         }
00496       }
00497     }
00498 
00499     
00500     
00501     
00502     if (current_len == 0) continue;
00503 
00504     
00505 
00506 
00507  
00508     if (!adin_cut_on && is_valid_data == FALSE && current_len > 0) {
00509       is_valid_data = TRUE;
00510     }
00511 
00512     
00513     
00514     
00515     
00516     wstep = DEFAULT_WSTEP;      
00517 
00518     
00519     
00520 
00521 
00522 
00523 
00524 
00525 
00526 
00527 
00528 
00529 #ifdef HAVE_PTHREAD
00530     if (enable_thread) imax = current_len; 
00531     else imax = (current_len < wstep) ? current_len : wstep; 
00532 #else
00533     imax = (current_len < wstep) ? current_len : wstep; 
00534 #endif
00535     
00536     
00537     if (wstep > current_len) wstep = current_len;
00538 
00539 #ifdef THREAD_DEBUG
00540     printf("process %d samples by %d step\n", imax, wstep);
00541 #endif
00542 
00543 #ifdef HAVE_PTHREAD
00544     if (enable_thread) {
00545       
00546       pthread_mutex_lock(&mutex);
00547       transfer_online_local = transfer_online;
00548       pthread_mutex_unlock(&mutex);
00549     }
00550 #endif
00551 
00552     
00553     
00554     
00555     i = 0;
00556     while (i + wstep <= imax) {
00557       
00558       if (adin_cut_on) {
00559 
00560         
00561         
00562         
00563         
00564 
00565 
00566         
00567         
00568         
00569         zc = count_zc_e(&(buffer[i]), wstep);
00570         
00571         if (zc > noise_zerocross) { 
00572           
00573           if (is_valid_data == FALSE) {
00574             
00575             
00576             
00577             
00578             is_valid_data = TRUE;   
00579             nc = 0;
00580 #ifdef THREAD_DEBUG
00581             printf("detect on\n");
00582 #endif
00583             
00584             
00585             
00586             
00587             
00588 
00589 
00590 
00591             if ( ad_process != NULL
00592 #ifdef HAVE_PTHREAD
00593                  && (!enable_thread || !ignore_speech_while_recog || transfer_online_local)
00594 #endif
00595                  ) {
00596               
00597               zc_copy_buffer(cbuf, &len);
00598               
00599 
00600 
00601 
00602 
00603               if (len - wstep > 0) {
00604 #ifdef THREAD_DEBUG
00605                 printf("callback for buffered samples (%d bytes)\n", len - wstep);
00606 #endif
00607                 ad_process_ret = (*ad_process)(cbuf, len - wstep);
00608                 switch(ad_process_ret) {
00609                 case 1:         
00610 #ifdef HAVE_PTHREAD
00611                   if (enable_thread) {
00612                     
00613                     pthread_mutex_lock(&mutex);
00614                     transfer_online = transfer_online_local = FALSE;
00615                     pthread_mutex_unlock(&mutex);
00616                   } else {
00617                     
00618                     end_status = 1;
00619                     adin_purge(i);
00620                     goto break_input;
00621                   }
00622                   break;
00623 #else
00624                   
00625                   end_status = 1;
00626                   adin_purge(i);
00627                   goto break_input;
00628 #endif
00629                 case -1:                
00630                   
00631                   end_status = -1;
00632                   goto break_input;
00633                 }
00634               }
00635             }
00636             
00637           } else {              
00638             
00639             
00640             
00641             
00642             if (nc > 0) {
00643               
00644               
00645               
00646               
00647               
00648 #ifdef THREAD_DEBUG
00649               printf("re-triggered\n");
00650 #endif
00651               
00652               nc = 0;
00653 
00654 #ifdef TMP_FIX_200602
00655               if (ad_process != NULL
00656 #ifdef HAVE_PTHREAD
00657                   && (!enable_thread || !ignore_speech_while_recog || transfer_online_local)
00658 #endif
00659                   ) {
00660 #endif
00661               
00662               
00663               
00664               
00665               
00666 
00667 
00668 
00669 
00670 
00671 
00672               if (sblen > 0) {
00673 #ifdef THREAD_DEBUG
00674                 printf("callback for swapped %d samples\n", sblen);
00675 #endif
00676                 ad_process_ret = (*ad_process)(swapbuf, sblen);
00677                 sblen = 0;
00678                 switch(ad_process_ret) {
00679                 case 1:         
00680 #ifdef HAVE_PTHREAD
00681                   if (enable_thread) {
00682                     
00683                     pthread_mutex_lock(&mutex);
00684                     transfer_online = transfer_online_local = FALSE;
00685                     pthread_mutex_unlock(&mutex);
00686                   } else {
00687                     
00688                     end_status = 1;
00689                     adin_purge(i);
00690                     goto break_input;
00691                   }
00692                   break;
00693 #else
00694                   
00695                   end_status = 1;
00696                   adin_purge(i);
00697                   goto break_input;
00698 #endif
00699                 case -1:                
00700                   
00701                   end_status = -1;
00702                   goto break_input;
00703                 }
00704               }
00705 #ifdef TMP_FIX_200602
00706               }
00707 #endif
00708             }
00709           } 
00710         } else if (is_valid_data == TRUE) {
00711           
00712           
00713           
00714           
00715           
00716 #ifdef THREAD_DEBUG
00717           printf("TRAILING SILENCE\n");
00718 #endif
00719           if (nc == 0) {
00720             
00721             rest_tail = sbsize - c_length;
00722             sblen = 0;
00723 #ifdef THREAD_DEBUG
00724             printf("start tail silence, rest_tail = %d\n", rest_tail);
00725 #endif
00726           }
00727 
00728           
00729           nc++;
00730         }
00731       } 
00732       
00733       
00734       
00735       
00736       
00737       
00738       if (adin_cut_on && is_valid_data && nc > 0 && rest_tail == 0) {
00739         
00740         
00741 
00742 
00743 
00744 
00745 
00746         
00747 #ifdef THREAD_DEBUG
00748         printf("tail silence over, store to swap buffer (nc=%d, rest_tail=%d, sblen=%d-%d)\n", nc, rest_tail, sblen, sblen+wstep);
00749 #endif
00750         if (sblen + wstep > sbsize) {
00751           j_printerr("Error: swapbuf exceeded!\n");
00752         }
00753         memcpy(&(swapbuf[sblen]), &(buffer[i]), wstep * sizeof(SP16));
00754         sblen += wstep;
00755         
00756       } else {
00757 
00758         
00759 
00760 
00761 
00762 
00763         
00764 #ifdef TMP_FIX_200602
00765         if (!adin_cut_on || is_valid_data == TRUE) {
00766 #else
00767         if(
00768            (!adin_cut_on || is_valid_data == TRUE)
00769 #ifdef HAVE_PTHREAD
00770            && (!enable_thread || !ignore_speech_while_recog || transfer_online_local)
00771 #endif
00772            ) {
00773 #endif
00774           if (nc > 0) {
00775             
00776 
00777             if (rest_tail < wstep) rest_tail = 0;
00778             else rest_tail -= wstep;
00779 #ifdef THREAD_DEBUG
00780             printf("%d processed, rest_tail=%d\n", wstep, rest_tail);
00781 #endif
00782           }
00783 #ifdef TMP_FIX_200602
00784           if (ad_process != NULL
00785 #ifdef HAVE_PTHREAD
00786               && (!enable_thread || !ignore_speech_while_recog || transfer_online_local)
00787 #endif
00788               ) {
00789 
00790 #else
00791           if ( ad_process != NULL ) {
00792 #endif
00793 #ifdef THREAD_DEBUG
00794             printf("callback for input sample [%d-%d]\n", i, i+wstep);
00795 #endif
00796             
00797             ad_process_ret = (*ad_process)(&(buffer[i]),  wstep);
00798             switch(ad_process_ret) {
00799             case 1:             
00800 #ifdef HAVE_PTHREAD
00801               if (enable_thread) {
00802                 
00803                 pthread_mutex_lock(&mutex);
00804                 transfer_online = transfer_online_local = FALSE;
00805                 pthread_mutex_unlock(&mutex);
00806               } else {
00807                 
00808                 adin_purge(i+wstep);
00809                 end_status = 1;
00810                 goto break_input;
00811               }
00812               break;
00813 #else
00814               
00815               adin_purge(i+wstep);
00816               end_status = 1;
00817               goto break_input;
00818 #endif
00819             case -1:            
00820               
00821               end_status = -1;
00822               goto break_input;
00823             }
00824           }
00825         }
00826       } 
00827 
00828       
00829       if (adin_cut_on && is_valid_data && nc >= nc_max) {
00830         
00831         
00832         
00833         
00834 #ifdef THREAD_DEBUG
00835         printf("detect off\n");
00836 #endif
00837         
00838         is_valid_data = FALSE;  
00839         sblen = 0;
00840 #ifdef HAVE_PTHREAD
00841         if (enable_thread) { 
00842           pthread_mutex_lock(&mutex);
00843           transfer_online = transfer_online_local = FALSE;
00844           pthread_mutex_unlock(&mutex);
00845         } else {
00846           adin_purge(i+wstep);
00847           end_status = 1;
00848           goto break_input;
00849         }
00850 #else
00851         adin_purge(i+wstep);
00852         end_status = 1;
00853         goto break_input;
00854 #endif
00855       }
00856 
00857       
00858       
00859       
00860       i += wstep;               
00861     }
00862     
00863     
00864     adin_purge(i);
00865 
00866     
00867     if (end_of_stream && bp == 0) break;
00868   }
00869 
00870 break_input:
00871 
00872   
00873   
00874   
00875   
00876   if (ad_pause != NULL) {
00877     if ((*ad_pause)() == FALSE) {
00878       j_printerr("Error: failed to pause recording\n");
00879       end_status = -1;
00880     }
00881   }
00882 
00883   if (end_of_stream) {                  
00884     if (bp == 0) {              
00885       
00886       if (adin_cut_on) end_count_zc_e();
00887       need_init = TRUE;         
00888     }
00889     end_status = (bp) ? 1 : 0;
00890   }
00891   
00892   return(end_status);
00893 }
00894 
00895 
00896 
00897 
00898 
00899 
00900 
00901 
00902 #ifdef HAVE_PTHREAD
00903 
00904 
00905 
00906 
00907 
00908 
00909 
00910 
00919 static int
00920 adin_store_buffer(SP16 *now, int len)
00921 {
00922   if (speechlen + len > MAXSPEECHLEN) {
00923     
00924     pthread_mutex_lock(&mutex);
00925     adinthread_buffer_overflowed = TRUE;
00926     pthread_mutex_unlock(&mutex);
00927     return(0);
00928   }
00929   pthread_mutex_lock(&mutex);
00930   memcpy(&(speech[speechlen]), now, len * sizeof(SP16));
00931   speechlen += len;
00932   pthread_mutex_unlock(&mutex);
00933 #ifdef THREAD_DEBUG
00934   printf("input: stored %d samples, total=%d\n", len, speechlen);
00935 #endif
00936   
00937   
00938   return(0);                    
00939 }
00940 
00946 void
00947 adin_thread_input_main(void *dummy)
00948 {
00949   adin_cut(adin_store_buffer, NULL);
00950 }
00951 
00956 static void
00957 adin_thread_create()
00958 {
00959   
00960   speechlen = 0;
00961   speech = (SP16 *)mymalloc(sizeof(SP16) * MAXSPEECHLEN);
00962 
00963   transfer_online = FALSE; 
00964   adinthread_buffer_overflowed = FALSE;
00965 
00966   if (pthread_mutex_init(&(mutex), NULL) != 0) { 
00967     j_error("Error: pthread: cannot initialize mutex\n");
00968   }
00969   if (pthread_create(&adin_thread, NULL, (void *)adin_thread_input_main, NULL) != 0) {
00970     j_error("Error: pthread: failed to create AD-in thread\n");
00971   }
00972   if (pthread_detach(adin_thread) != 0) { 
00973     j_error("Error: pthread: failed to detach AD-in thread\n");
00974   }
00975   j_printerr("AD-in thread created\n");
00976 }
00977 
00978 
00979 
00980 
00981 
00982 
00996 static int
00997 adin_thread_process(int (*ad_process)(SP16 *, int), int (*ad_check)())
00998 {
00999   int prev_len, nowlen;
01000   int ad_process_ret;
01001   int i;
01002   boolean overflowed_p;
01003   boolean transfer_online_local;
01004 
01005   
01006   pthread_mutex_lock(&mutex);
01007    
01008   transfer_online = TRUE;
01009 #ifdef THREAD_DEBUG
01010   printf("process: reset, speechlen = %d, online=%d\n", speechlen, transfer_online);
01011 #endif
01012   pthread_mutex_unlock(&mutex);
01013 
01014   
01015   prev_len = 0;
01016   for(;;) {
01017     
01018     pthread_mutex_lock(&mutex);
01019     nowlen = speechlen;
01020     overflowed_p = adinthread_buffer_overflowed;
01021     transfer_online_local = transfer_online;
01022     pthread_mutex_unlock(&mutex);
01023     
01024     if (overflowed_p) {
01025       j_printerr("Warning: too long input (> %d samples), segmented now\n", MAXSPEECHLEN);
01026       
01027       pthread_mutex_lock(&mutex);
01028       adinthread_buffer_overflowed = FALSE;
01029       speechlen = 0;
01030       transfer_online = transfer_online_local = FALSE;
01031       pthread_mutex_unlock(&mutex);
01032       return(1);                
01033     }
01034     
01035     if (ad_check != NULL) {
01036       if ((i = (*ad_check)()) < 0) {
01037         if ((i == -1 && nowlen == 0) || i == -2) {
01038           pthread_mutex_lock(&mutex);
01039           transfer_online = transfer_online_local = FALSE;
01040           speechlen = 0;
01041           pthread_mutex_unlock(&mutex);
01042           return(-2);
01043         }
01044       }
01045     }
01046     if (prev_len < nowlen) {
01047 #ifdef THREAD_DEBUG
01048       printf("process: proceed [%d-%d]\n",prev_len, nowlen);
01049 #endif
01050       
01051       
01052 
01053 
01054 
01055 
01056       
01057       if (ad_process != NULL) {
01058         ad_process_ret = (*ad_process)(&(speech[prev_len]),  nowlen - prev_len);
01059 #ifdef THREAD_DEBUG
01060         printf("ad_process_ret=%d\n",ad_process_ret);
01061 #endif
01062         switch(ad_process_ret) {
01063         case 1:                 
01064           
01065           
01066           pthread_mutex_lock(&mutex);
01067           if(speechlen > nowlen) {
01068             memmove(buffer, &(buffer[nowlen]), (speechlen - nowlen) * sizeof(SP16));
01069             speechlen = speechlen - nowlen;
01070           } else {
01071             speechlen = 0;
01072           }
01073           transfer_online = transfer_online_local = FALSE;
01074           pthread_mutex_unlock(&mutex);
01075           
01076           return(1);            
01077         case -1:                
01078           pthread_mutex_lock(&mutex);
01079           transfer_online = transfer_online_local = FALSE;
01080           pthread_mutex_unlock(&mutex);
01081           return(-1);           
01082         }
01083       }
01084       prev_len = nowlen;
01085     } else {
01086       if (transfer_online_local == FALSE) {
01087         
01088         
01089         pthread_mutex_lock(&mutex);
01090         speechlen = 0;
01091         pthread_mutex_unlock(&mutex);
01092         break;
01093       }
01094       usleep(100000);               
01095     }
01096   }
01097 
01098   
01099   
01100   return(1);
01101 }
01102 #endif 
01103 
01104 
01105 
01106 
01125 int
01126 adin_go(int (*ad_process)(SP16 *, int), int (*ad_check)())
01127 {
01128 #ifdef HAVE_PTHREAD
01129   if (enable_thread) {
01130     return(adin_thread_process(ad_process, ad_check));
01131   }
01132 #endif
01133   return(adin_cut(ad_process, ad_check));
01134 }