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 }