一般来说,和设置的threshold参数关系很大,但是这里仅是要一个算法。
或者说,从这侦测到的第一个认为是静音的分组开始,就丢弃还是要等等。如何平滑,从说话到静音,和从静音到说话的过程。
多谢
首先,这不是一个简单的问题。
静音检测,不只是检测通话人是否Talking,更重要的是如何在通话环境中参杂着其他噪声
时如何能够排除这些噪声干扰,并正确的得到检验结果。
平滑静声与说话之间的过程也是一个重要的问题。
呵呵,期待大家能将已实现的技术和经验拿出来共享 :)
是呀,这是一个应该很有用的题目。
所以所谓的静音检测,一般正式的叫法是:静噪抑制技术,甚至还包含有一部分的回音消除,如果是在时延较大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的语音设备音量调整的。那位可不可以指教如何很方便的做?
多谢了。