如何在 PCM 音频中使用 IMediaSample 检测静音

Posted

技术标签:

【中文标题】如何在 PCM 音频中使用 IMediaSample 检测静音【英文标题】:How to detect silence with IMediaSample in PCM audio 【发布时间】:2012-07-31 09:39:20 【问题描述】:

我需要使用 IMediaSample 检测 PCM 音频流中的静音。信号由电视提供,通过光缆与 PC 连接到 Prodigy 7.1 HiFi 声卡。到目前为止,我有这个:

bool detectSound(IMediaSample *pSamples)

    BYTE *pData;
    pSamples->GetPointer(&pData);
    long size = pSamples->GetActualDataLength();

    long nulls = 0;
    for(long i = 0; i < size; ++i) 
        if(pData[i] == 0)
            ++nulls;
    

    /* 0.9 to eliminate interference */
    long max_nulls = (long) (0.9 * size);
    if(nulls > max_nulls)                  /* STOP */
        /* no audio */
        return false;
    
    else 
        /* audio available */
        return true;
    

问题是,如果我在标记为“STOP”的行处设置断点,无论我是否将电视静音,nulls 几乎总是具有相同的值并且小于 max_nulls。我注意到 pData[i] 的值总是 0 或 255。(奇怪还是不奇怪?)

可能我不明白这个“数据”到底是什么以及如何解释它。我可以肯定的是,如果没有音频,那么波形中的所有采样值应该几乎为 0。

你能验证我的想法吗?提前致谢。

日食

编辑:

问题出在驱动程序和 AC3 过滤器设置的某个地方,因为在“SPDIF 测试”中,我发现 DirectSound 不支持 44.1 kHz、48 kHz 和 32 kHz。 Roman的想法是正确的,当我解决这个问题时会起作用。

【问题讨论】:

【参考方案1】:

更好的方法是找出 PCM 数据是什么,发布的问题的答案将是微不足道的。

更快的方法是:

将这些音频数据字节视为 SHORT 值(您没有提到,但我想您的音频是 16 位的) 最好是拆分成通道单独处理 计算standard deviation 静默是当/如果计算值低于某个小阈值

【讨论】:

我同意你的观点,但是无论是否静音(我将每两个字节视为一个 16 位样本),计算的值都会在时间上保持不变。首先,IMediaSample 返回的数据缓冲区包含什么?是否有从波形中抓取的 16 位样本值?这是我现在的基本问题。 缓冲区通常包含以下数据:PCM Waveform-Audio Data Format 我确实像你说的那样:我将样本拆分为通道,我使用带符号的 short 来存储每个通道样本 2 个字节,但似乎真正静音的值与声音(和声音声音很大,大约停止了电视的规模)。值范围为 -80 - +80。我使用了你提供给我的那个网站的信息。 那么音频媒体类型是什么(WAVEFORMATEX结构字段)?我假设是 16 位,但您应该指定。 是16。可能是声卡驱动的问题。因为它无法识别 AC-3 声音(我不得不在电视中切换到 PCM)。

以上是关于如何在 PCM 音频中使用 IMediaSample 检测静音的主要内容,如果未能解决你的问题,请参考以下文章

如何在 iOS 上录制 PCM 音频文件?

VLC如何在普通PC上播放24位PCM音频?

如何在 pcm 流 (c#) 中查找音频功率 (db)

如何在 iOS 5 上以编程方式规范化 PCM 音频样本?

如何播放 PCM-24 音频?

如何将 PCM 音频流转换为在线播放