请教静音检测算法,思想或者源码皆可。 首先,这不是一个简单的问题。静音检测,不只是检测通话人是否Talking,更重要的是如何在通话环境中参杂着其他噪声时如何能够排除这些噪声干扰,并正确的得到检验结果。平滑静声与说话之间的过程也是一个重要的问题。呵呵,期待大家能将已实现的技术和经验拿出来共享 :) 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 是呀,这是一个应该很有用的题目。所以所谓的静音检测,一般正式的叫法是:静噪抑制技术,甚至还包含有一部分的回音消除,如果是在时延较大ip网,也是必须的。当然,首先需要的是一块比较好的声卡和一个抑噪耳机,(比如viaVoice带的)我这里只有一个比较原始的思路:设置一个threshold值,一个比率。检测语音的分组,如果其中大部分数据都在门阈值以下,就认为是背景噪音或者说静默时间的语音包,予以丢弃。但是这里涉及一个参数设置问题,一个平滑问题。所以还是要请教大家,希望大家关注。 在实际中还有一个更为普遍的问题:就是白噪音的问题,对于参数的设定就更为重要了。目前是这样做的,但是效果不是非常好。///________________________________________________________________________/// Method: DetectSilence/// Params:/// lpData: the data for detect /// inLen: data length /// Function:/// detect the data. discard the background noise and other /// noise. the parameter is sensible. ///________________________________________________________________________DWORD CAudioMgr::DetectSilence(LPBYTE lpData, DWORD inLen){ static bool bSpeakingState = TRUE; // 指明目前的状态是通话还是静默 static unsigned int nConsecutive = 0; // 用来计算连续出现的某种类型的包 bool bNoisePacket; // 当前检测的语音包类型(判断) long hit = 0; // 要来计算语音包中符合条件的位数。long足够了 unsigned int i; // 循环变量 // 推测当前语音包类型 for(i = 0; i < inLen; i++) { if((lpData[i] <= 0 + constThreshold ) || (lpData[i] >= 255 - constThreshold)) hit++; } float ratio = (float)hit/ inLen; if (ratio > constHitratio) { bNoisePacket = TRUE; } else { bNoisePacket = FALSE; } if( TRUE == bSpeakingState) // 如果目前是通话状态 { if(FALSE == bNoisePacket) // 如果目前的包断定为语音包 { nConsecutive = 0; // 计数清零 return inLen; } else // 如果目前是静音包 { nConsecutive++; if( constNoiseCons < nConsecutive ) // 如果已经连续出现了足够的静音包 { nConsecutive = 0 ; // 计数清零 TRACE("从通话状态转化到静音状态!**********\n"); bSpeakingState = FALSE; // 转换到静音状态 return 0; } else { return inLen; // 仍然提交 } } } else // 如果当前是静音状态 { if(TRUE == bNoisePacket) // 如果目前的包断定为静音包 { nConsecutive = 0; // 计数清零 return 0; } else // 如果目前是语音包 { nConsecutive++; if( constVoiceCons < nConsecutive ) // 如果已经连续出现了足够的语音包 { nConsecutive = 0 ; // 计数清零 TRACE("*********从静音状态转化到通话状态!\n"); bSpeakingState = TRUE; // 转换到静音状态 return inLen; } else { return 0; // 否则仍然丢弃 } } }} 但是在实际使用中:上面我写的算法在经过调整参数之后,可以较为满意的侦测到静默的状态,但是在网络传输中收到的语音包会出现较明显的滞后。不知道为什么?我每次都是及时发送出数据包的。还有,按理说应该是在应用程序运行前,出现类似于MSN Message Service的语音设备音量调整的。那位可不可以指教如何很方便的做?多谢了。 音频编码格式使用ACM转换到GSM格式,应该可以吧。本来也想在必要时也可以采用g.729A。不过感觉没必要。能不能有人给出一点经验。 字符串拷贝的问题 新手求助:WTL 如何实现TreeView? VC中注册表的用法 vc调用WinExec为何无法结束程序啊 windows服务程序,枚举登录用户打开的窗口失败,将服务做成exe,就能成功,谁有这方面的经验么,指点下,谢谢!! 求助:关于在界面上插入图片的问题 pane 和window区别?请帮我讲讲`pane 是什么东西? 如何实现橡皮线功能? STL LIST 如何在视图类中响应定时器函数; 有高手吗,能否回答关于EDIT控件赋值的问题? 为什么总没有人帮助我,我已经提了很多问题......。能否回答关于EDIT控件赋值的问题?
所以所谓的静音检测,一般正式的叫法是:静噪抑制技术,甚至还包含有一部分的回音消除,如果是在时延较大ip网,也是必须的。当然,首先需要的是一块比较好的声卡和一个抑噪耳机,(比如viaVoice带的)我这里只有一个比较原始的思路:设置一个threshold值,一个比率。检测语音的分组,如果其中大部分数据都在门阈值以下,就认为是背景噪音或者说静默时间的语音包,予以丢弃。但是这里涉及一个参数设置问题,一个平滑问题。所以还是要请教大家,希望大家关注。
目前是这样做的,但是效果不是非常好。
///________________________________________________________________________
/// Method: DetectSilence
/// Params:
/// lpData: the data for detect
/// inLen: data length
/// Function:
/// detect the data. discard the background noise and other
/// noise. the parameter is sensible.
///________________________________________________________________________DWORD CAudioMgr::DetectSilence(LPBYTE lpData, DWORD inLen)
{
static bool bSpeakingState = TRUE; // 指明目前的状态是通话还是静默
static unsigned int nConsecutive = 0; // 用来计算连续出现的某种类型的包
bool bNoisePacket; // 当前检测的语音包类型(判断)
long hit = 0; // 要来计算语音包中符合条件的位数。long足够了
unsigned int i; // 循环变量 // 推测当前语音包类型 for(i = 0; i < inLen; i++) {
if((lpData[i] <= 0 + constThreshold )
|| (lpData[i] >= 255 - constThreshold))
hit++;
}
float ratio = (float)hit/ inLen;
if (ratio > constHitratio)
{
bNoisePacket = TRUE;
}
else
{
bNoisePacket = FALSE;
}
if( TRUE == bSpeakingState) // 如果目前是通话状态
{
if(FALSE == bNoisePacket) // 如果目前的包断定为语音包
{
nConsecutive = 0; // 计数清零
return inLen;
}
else // 如果目前是静音包
{
nConsecutive++;
if( constNoiseCons < nConsecutive ) // 如果已经连续出现了足够的静音包
{
nConsecutive = 0 ; // 计数清零
TRACE("从通话状态转化到静音状态!**********\n");
bSpeakingState = FALSE; // 转换到静音状态
return 0;
}
else
{
return inLen; // 仍然提交
}
}
}
else // 如果当前是静音状态
{
if(TRUE == bNoisePacket) // 如果目前的包断定为静音包
{
nConsecutive = 0; // 计数清零
return 0;
}
else // 如果目前是语音包
{
nConsecutive++;
if( constVoiceCons < nConsecutive ) // 如果已经连续出现了足够的语音包
{
nConsecutive = 0 ; // 计数清零
TRACE("*********从静音状态转化到通话状态!\n");
bSpeakingState = TRUE; // 转换到静音状态
return inLen;
}
else
{
return 0; // 否则仍然丢弃
}
}
}
}
本来也想在必要时也可以采用g.729A。不过感觉没必要。能不能有人给出一点经验。