如何在 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 检测静音的主要内容,如果未能解决你的问题,请参考以下文章