首先,这不是一个简单的问题。静音检测,不只是检测通话人是否Talking,更重要的是如何在通话环境中参杂着其他噪声时如何能够排除这些噪声干扰,并正确的得到检验结果。平滑静声与说话之间的过程也是一个重要的问题。呵呵,期待大家能将已实现的技术和经验拿出来共享 :)

解决方案 »

  1.   

    是呀,这是一个应该很有用的题目。
    所以所谓的静音检测,一般正式的叫法是:静噪抑制技术,甚至还包含有一部分的回音消除,如果是在时延较大ip网,也是必须的。当然,首先需要的是一块比较好的声卡和一个抑噪耳机,(比如viaVoice带的)我这里只有一个比较原始的思路:设置一个threshold值,一个比率。检测语音的分组,如果其中大部分数据都在门阈值以下,就认为是背景噪音或者说静默时间的语音包,予以丢弃。但是这里涉及一个参数设置问题,一个平滑问题。所以还是要请教大家,希望大家关注。
      

  2.   

    在实际中还有一个更为普遍的问题:就是白噪音的问题,对于参数的设定就更为重要了。
    目前是这样做的,但是效果不是非常好。
    ///________________________________________________________________________
    /// 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; // 否则仍然丢弃
    }
    }
    }
    }
      

  3.   

    但是在实际使用中:上面我写的算法在经过调整参数之后,可以较为满意的侦测到静默的状态,但是在网络传输中收到的语音包会出现较明显的滞后。不知道为什么?我每次都是及时发送出数据包的。还有,按理说应该是在应用程序运行前,出现类似于MSN Message Service的语音设备音量调整的。那位可不可以指教如何很方便的做?多谢了。
      

  4.   

    音频编码格式使用ACM转换到GSM格式,应该可以吧。
    本来也想在必要时也可以采用g.729A。不过感觉没必要。能不能有人给出一点经验。