📄 adin-cut.c
字号:
static intadin_store_buffer(SP16 *now, int len, Recog *recog){ ADIn *a; a = recog->adin; if (a->speechlen + len > MAXSPEECHLEN) { /* just mark as overflowed, and continue this thread */ pthread_mutex_lock(&(a->mutex)); a->adinthread_buffer_overflowed = TRUE; pthread_mutex_unlock(&(a->mutex)); return(0); } pthread_mutex_lock(&(a->mutex)); memcpy(&(a->speech[a->speechlen]), now, len * sizeof(SP16)); a->speechlen += len; pthread_mutex_unlock(&(a->mutex));#ifdef THREAD_DEBUG jlog("DEBUG: input: stored %d samples, total=%d\n", len, a->speechlen);#endif return(0); /* continue */}/** * <EN> * A/D-in thread main function. * </EN> * <JA> * A/D-in スレッドのメイン簇眶. * </JA> * * @param dummy [in] a dummy data, not used. */static voidadin_thread_input_main(void *dummy){ Recog *recog; int ret; recog = dummy; ret = adin_cut(adin_store_buffer, NULL, recog); if (ret == -1) { /* error */ jlog("Error: adin thread exit with error\n"); } else if (ret == 0) { /* EOF */ jlog("Stat: adin thread end with EOF\n"); } recog->adin->adinthread_ended = TRUE; /* return to end this thread */}/** * <EN> * Start new A/D-in thread, and initialize buffer. * </EN> * <JA> * バッファを介袋步して A/D-in スレッドを倡幌する. * </JA> * @param recog [in] engine instance * * @callergraph * @callgraph */booleanadin_thread_create(Recog *recog){ ADIn *a; a = recog->adin; /* init storing buffer */ a->speech = (SP16 *)mymalloc(sizeof(SP16) * MAXSPEECHLEN); a->speechlen = 0; a->transfer_online = FALSE; /* tell adin-mic thread to wait at initial */ a->adinthread_buffer_overflowed = FALSE; a->adinthread_ended = FALSE; if (pthread_mutex_init(&(a->mutex), NULL) != 0) { /* error */ jlog("ERROR: adin_thread_create: failed to initialize mutex\n"); return FALSE; } if (pthread_create(&(recog->adin->adin_thread), NULL, (void *)adin_thread_input_main, recog) != 0) { jlog("ERROR: adin_thread_create: failed to create AD-in thread\n"); return FALSE; } if (pthread_detach(recog->adin->adin_thread) != 0) { /* not join, run forever */ jlog("ERROR: adin_thread_create: failed to detach AD-in thread\n"); return FALSE; } jlog("STAT: AD-in thread created\n"); return TRUE;}/** * <EN> * Delete A/D-in thread * </EN> * <JA> * A/D-in スレッドを姜位する * </JA> * @param recog [in] engine instance * * @callergraph * @callgraph */booleanadin_thread_cancel(Recog *recog){ ADIn *a; int ret; if (recog->adin->adinthread_ended) return TRUE; ret = pthread_cancel(recog->adin->adin_thread); if (ret == 0) { jlog("STAT: AD-in thread deleted\n"); } else { if (ret == ESRCH) { jlog("STAT: adin_thread_cancel: no A/D-in thread\n"); } else { jlog("Error: adin_thread_cancel: failed to cancel A/D-in thread\n"); return FALSE; } } recog->adin->adinthread_ended = TRUE; return TRUE;}/****************************//* process thread functions *//****************************//** * <EN> * @brief Main processing function for thread mode. * * It waits for the new samples to be stored in @a speech by A/D-in thread, * and if found, process them. The interface are the same as adin_cut(). * </EN> * <JA> * @brief スレッドモ〖ド脱メイン簇眶 * * この簇眶は A/D-in スレッドによってサンプルが瘦赂されるのを略ち· * 瘦赂されたサンプルを界肌借妄していきます. 苞眶や手り猛は adin_cut() と * 票办です. * </JA> * * @param ad_process [in] function to process triggerted input. * @param ad_check [in] function to be called periodically. * @param recog [in] engine instance * * @return 2 when input termination requested by ad_process(), 1 when * if detect end of an input segment (down trigger detected after up * trigger), 0 when reached end of input device, -1 on error, -2 when * input termination requested by ad_check(). */static intadin_thread_process(int (*ad_process)(SP16 *, int, Recog *), int (*ad_check)(Recog *), Recog *recog){ int prev_len, nowlen; int ad_process_ret; int i; boolean overflowed_p; boolean transfer_online_local; boolean ended_p; ADIn *a; a = recog->adin; /* reset storing buffer --- input while recognition will be ignored */ pthread_mutex_lock(&(a->mutex)); /*if (speechlen == 0) transfer_online = TRUE;*/ /* tell adin-mic thread to start recording */ a->transfer_online = TRUE;#ifdef THREAD_DEBUG jlog("DEBUG: process: reset, speechlen = %d, online=%d\n", a->speechlen, a->transfer_online);#endif pthread_mutex_unlock(&(a->mutex)); /* main processing loop */ prev_len = 0; for(;;) { /* get current length (locking) */ pthread_mutex_lock(&(a->mutex)); nowlen = a->speechlen; overflowed_p = a->adinthread_buffer_overflowed; transfer_online_local = a->transfer_online; ended_p = a->adinthread_ended; pthread_mutex_unlock(&(a->mutex)); /* check if thread is alive */ if (ended_p) { /* adin thread has already exited, so return EOF to stop this input */ return(0); } /* check if other input thread has overflowed */ if (overflowed_p) { jlog("WARNING: adin_thread_process: too long input (> %d samples), segmented now\n", MAXSPEECHLEN); /* segment input here */ pthread_mutex_lock(&(a->mutex)); a->adinthread_buffer_overflowed = FALSE; a->speechlen = 0; a->transfer_online = transfer_online_local = FALSE; pthread_mutex_unlock(&(a->mutex)); return(1); /* return with segmented status */ } /* callback poll */ if (ad_check != NULL) { if ((i = (*(ad_check))(recog)) < 0) { if ((i == -1 && nowlen == 0) || i == -2) { pthread_mutex_lock(&(a->mutex)); a->transfer_online = transfer_online_local = FALSE; a->speechlen = 0; pthread_mutex_unlock(&(a->mutex)); return(-2); } } } if (prev_len < nowlen) {#ifdef THREAD_DEBUG jlog("DEBUG: process: proceed [%d-%d]\n",prev_len, nowlen);#endif /* got new sample, process */ /* As the speech[] buffer is monotonously increase, content of speech buffer [prev_len..nowlen] would not alter in both threads So locking is not needed while processing. */ /*jlog("DEBUG: main: read %d-%d\n", prev_len, nowlen);*/ if (ad_process != NULL) { ad_process_ret = (*ad_process)(&(a->speech[prev_len]), nowlen - prev_len, recog);#ifdef THREAD_DEBUG jlog("DEBUG: ad_process_ret=%d\n", ad_process_ret);#endif switch(ad_process_ret) { case 1: /* segmented */ /* segmented by callback function */ /* purge processed samples and keep transfering */ pthread_mutex_lock(&(a->mutex)); if(a->speechlen > nowlen) { memmove(a->speech, &(a->speech[nowlen]), (a->speechlen - nowlen) * sizeof(SP16)); a->speechlen -= nowlen; } else { a->speechlen = 0; } a->transfer_online = transfer_online_local = FALSE; pthread_mutex_unlock(&(a->mutex)); /* keep transfering */ return(2); /* return with segmented status */ case -1: /* error */ pthread_mutex_lock(&(a->mutex)); a->transfer_online = transfer_online_local = FALSE; pthread_mutex_unlock(&(a->mutex)); return(-1); /* return with error */ } } if (a->rehash) { /* rehash */ pthread_mutex_lock(&(a->mutex)); if (debug2_flag) jlog("STAT: adin_cut: rehash from %d to %d\n", a->speechlen, a->speechlen - prev_len); a->speechlen -= prev_len; nowlen -= prev_len; memmove(a->speech, &(a->speech[prev_len]), a->speechlen * sizeof(SP16)); pthread_mutex_unlock(&(a->mutex)); a->rehash = FALSE; } prev_len = nowlen; } else { if (transfer_online_local == FALSE) { /* segmented by zero-cross */ /* reset storing buffer for next input */ pthread_mutex_lock(&(a->mutex)); a->speechlen = 0; pthread_mutex_unlock(&(a->mutex)); break; } usleep(50000); /* wait = 0.05sec*/ } } /* as threading assumes infinite input */ /* return value should be 1 (segmented) */ return(1);}#endif /* HAVE_PTHREAD *//** * <EN> * @brief Top function to start input processing * * If threading mode is enabled, this function simply enters to * adin_thread_process() to process triggered samples detected by * another running A/D-in thread. * * If threading mode is not available or disabled by either device requirement * or OS capability, this function simply calls adin_cut() to detect speech * segment from input device and process them concurrently by one process. * </EN> * <JA> * @brief 掐蜗借妄を乖うトップ簇眶 * * スレッドモ〖ドでは·この簇眶は adin_thead_process() を钙び叫し· * 润スレッドモ〖ドでは adin_cut() を木儡钙び叫す. 苞眶や手り猛は * adin_cut() と票办である. * </JA> * * @param ad_process [in] function to process triggerted input. * @param ad_check [in] function to be called periodically. * @param recog [in] engine instance * * @return 2 when input termination requested by ad_process(), 1 when * if detect end of an input segment (down trigger detected after up * trigger), 0 when reached end of input device, -1 on error, -2 when * input termination requested by ad_check(). * * @callergraph * @callgraph * */intadin_go(int (*ad_process)(SP16 *, int, Recog *), int (*ad_check)(Recog *), Recog *recog){ /* output listening start message */ callback_exec(CALLBACK_EVENT_SPEECH_READY, recog);#ifdef HAVE_PTHREAD if (recog->adin->enable_thread) { return(adin_thread_process(ad_process, ad_check, recog)); }#endif return(adin_cut(ad_process, ad_check, recog));}/** * <EN> * Call device-specific initialization. * </EN> * <JA> * デバイス巴赂の介袋步簇眶を钙び叫す. * </JA> * * @param a [in] A/D-in work area * @param freq [in] sampling frequency * @param arg [in] device-dependent argument * * @return TRUE if succeeded, FALSE if failed. * * @callergraph * @callgraph * */booleanadin_standby(ADIn *a, int freq, void *arg){ if (a->need_zmean) zmean_reset(); if (a->ad_standby != NULL) return(a->ad_standby(freq, arg)); return TRUE;}/** * <EN> * Call device-specific function to begin capturing of the audio stream. * </EN> * <JA> * 不の艰り哈みを倡幌するデバイス巴赂の簇眶を钙び叫す. * </JA> * * @param a [in] A/D-in work area * * @return TRUE on success, FALSE on failure. * * @callergraph * @callgraph * */booleanadin_begin(ADIn *a){ if (debug2_flag && a->input_side_segment) jlog("Stat: adin_begin: skip\n"); if (a->input_side_segment == FALSE) { if (a->need_zmean) zmean_reset(); if (a->ad_begin != NULL) return(a->ad_begin()); } return TRUE;}/** * <EN> * Call device-specific function to end capturing of the audio stream. * </EN> * <JA> * 不の艰り哈みを姜位するデバイス巴赂の簇眶を钙び叫す. * </JA> * * @param a [in] A/D-in work area * * @return TRUE on success, FALSE on failure. * * @callergraph * @callgraph */booleanadin_end(ADIn *a){ if (debug2_flag && a->input_side_segment) jlog("Stat: adin_end: skip\n"); if (a->input_side_segment == FALSE) { if (a->ad_end != NULL) return(a->ad_end()); } return TRUE;}/** * <EN> * Free memories of A/D-in work area. * </EN> * <JA> * 不艰り哈み脱ワ〖クエリアのメモリを倡庶する. * </JA> * * @param recog [in] engine instance * * @callergraph * @callgraph * */voidadin_free_param(Recog *recog){ ADIn *a; a = recog->adin; if (a->ds) { ds48to16_free(a->ds); a->ds = NULL; } if (a->adin_cut_on) { free_count_zc_e(&(a->zc)); } if (a->down_sample) { free(a->buffer48); } free(a->swapbuf); free(a->cbuf); free(a->buffer);#ifdef HAVE_PTHREAD if (a->speech) free(a->speech);#endif}/* end of file */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -