unimrcp-voice-activity音声検出

12552 ワード

unimrcpを研究してしばらく経ちましたが、その中でunimrcp voice acitveのアルゴリズムは、よくツッコミを入れられています.今日はunimrcp voice activityのこの簡単で乱暴なアルゴリズムを簡単に紹介します.
 
unimrcp音声活動検出はエネルギーによって制御され、いくつかの定数を設定します.
struct mpf_activity_detector_t {
/*        */
apr_size_t level_threshold;

/*    active       */
apr_size_t speech_timeout;
/*    inactive       */
apr_size_t silence_timeout;
/*           */
apr_size_t noinput_timeout;

/*       */
mpf_detector_state_e state;
/*            */
apr_size_t duration;
};

 
これらのパラメータの初期化値を見てみましょう.実際のテストに基づいて、後期に変更しました.
/** Create activity detector */
MPF_DECLARE(mpf_activity_detector_t*) mpf_activity_detector_create(apr_pool_t *pool)
{
    mpf_activity_detector_t *detector = apr_palloc(pool,sizeof(mpf_activity_detector_t));
    detector->level_threshold = 50; /* 0 .. 255 */
    detector->speech_timeout = 300; /* 0.3 s  = 300*/
    detector->silence_timeout = 1000; /* 0.3 s  =300 */
    detector->noinput_timeout = 5000; /* 5 s =5000*/
    detector->duration = 0;
    detector->state = DETECTOR_STATE_INACTIVITY;
    return detector;
}

 
重要な関数、エネルギーの計算を見てみましょう.
frameの情報に基づいてエネルギーを乱暴に加算するので,ノイズに対してはこのアルゴリズムは全く利用できない.このアルゴリズムの代わりにwebrtcのvoice activeを採用する方法については後述する.
static apr_size_t mpf_activity_detector_level_calculate(const mpf_frame_t *frame)
{
    apr_size_t sum = 0;
// apr_size_t count
= frame->codec_frame.size/2;
//
const apr_int16_t *cur = frame->codec_frame.buffer;
//
const apr_int16_t *end = cur + count; for(; cur < end; cur++) { if(*cur < 0) { sum -= *cur; } else { sum += *cur; } } // , , return sum / count; }

 
最後に見て、状態切替の過程を見て、次のmpf_activity_detector_プロセス関数は、主にframeの平均値を計算することによって、状態切替の論理を完了します.
処理プロセスには4つのステータスがあります.
ACTIVITY状態
INACTIVITY状態
     TRANS_ACTIVITY状態
     TRANS_INACTIVITY状態
ここでTRANS状態が中間状態であり、ACTIVITY状態とINACTIVITY状態に切り替わった場合、この状態を経て設定時間を積算する必要があり、満足していれば切り替わるが、そうでなければ切り替わらない.
/** Process current frame */
MPF_DECLARE(mpf_detector_event_e) mpf_activity_detector_process(mpf_activity_detector_t *detector, const mpf_frame_t *frame)
{
    mpf_detector_event_e det_event = MPF_DETECTOR_EVENT_NONE;
    apr_size_t level = 0;
    if((frame->type & MEDIA_FRAME_TYPE_AUDIO) == MEDIA_FRAME_TYPE_AUDIO) {
        /* first, calculate current activity level of processed frame */
// level
level = mpf_activity_detector_level_calculate(frame); #if 0 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Activity Detector --------------------- [%"APR_SIZE_T_FMT"]",level); #endif } /* INACTIVITY , level , , */ if(detector->state == DETECTOR_STATE_INACTIVITY) { if(level >= detector->level_threshold) { /* start to detect activity */ mpf_activity_detector_state_change(detector,DETECTOR_STATE_ACTIVITY_TRANSITION); } else { detector->duration += CODEC_FRAME_TIME_BASE; if(detector->duration >= detector->noinput_timeout) { /* detected noinput */ det_event = MPF_DETECTOR_EVENT_NOINPUT; } } } else if(detector->state == DETECTOR_STATE_ACTIVITY_TRANSITION) {
// 。
if(level >= detector->level_threshold) {
// level detector
->duration += CODEC_FRAME_TIME_BASE;
//
if(detector->duration >= detector->speech_timeout) { /* finally detected activity */
//
det_event = MPF_DETECTOR_EVENT_ACTIVITY; mpf_activity_detector_state_change(detector,DETECTOR_STATE_ACTIVITY); } } else { /* fallback to inactivity */
//
mpf_activity_detector_state_change(detector,DETECTOR_STATE_INACTIVITY); } } else if(detector->state == DETECTOR_STATE_ACTIVITY) {
//
if(level >= detector->level_threshold) {
// level , duration detector
->duration += CODEC_FRAME_TIME_BASE; } else { /* start to detect inactivity */
// inactivity
mpf_activity_detector_state_change(detector,DETECTOR_STATE_INACTIVITY_TRANSITION); } } else if(detector->state == DETECTOR_STATE_INACTIVITY_TRANSITION) {
// inactivity transtion
if(level >= detector->level_threshold) { /* fallback to activity */
// , activity
mpf_activity_detector_state_change(detector,DETECTOR_STATE_ACTIVITY); } else {
// , , , inactivity 。 detector
->duration += CODEC_FRAME_TIME_BASE; if(detector->duration >= detector->silence_timeout) { /* detected inactivity */ det_event = MPF_DETECTOR_EVENT_INACTIVITY; mpf_activity_detector_state_change(detector,DETECTOR_STATE_INACTIVITY); } } } return det_event; }