unimrcp-voice-activity音声検出
12552 ワード
unimrcpを研究してしばらく経ちましたが、その中でunimrcp voice acitveのアルゴリズムは、よくツッコミを入れられています.今日はunimrcp voice activityのこの簡単で乱暴なアルゴリズムを簡単に紹介します.
unimrcp音声活動検出はエネルギーによって制御され、いくつかの定数を設定します.
これらのパラメータの初期化値を見てみましょう.実際のテストに基づいて、後期に変更しました.
重要な関数、エネルギーの計算を見てみましょう.
frameの情報に基づいてエネルギーを乱暴に加算するので,ノイズに対してはこのアルゴリズムは全く利用できない.このアルゴリズムの代わりにwebrtcのvoice activeを採用する方法については後述する.
最後に見て、状態切替の過程を見て、次のmpf_activity_detector_プロセス関数は、主にframeの平均値を計算することによって、状態切替の論理を完了します.
処理プロセスには4つのステータスがあります.
ACTIVITY状態
INACTIVITY状態
TRANS_ACTIVITY状態
TRANS_INACTIVITY状態
ここでTRANS状態が中間状態であり、ACTIVITY状態とINACTIVITY状態に切り替わった場合、この状態を経て設定時間を積算する必要があり、満足していれば切り替わるが、そうでなければ切り替わらない.
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;
}