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