如何使用 C++ 从 PCM 样本中过滤出超出听力范围的数据?
Posted
技术标签:
【中文标题】如何使用 C++ 从 PCM 样本中过滤出超出听力范围的数据?【英文标题】:How do I filter out out-of-hearing-range data from PCM samples using C++? 【发布时间】:2013-02-21 17:06:53 【问题描述】:我有原始的 16 位 48khz pcm 数据。我需要剥离所有超出人类听觉范围的数据。
现在我只是对所有样本求和,然后除以样本数来计算峰值声级,但我需要减少误报。
我一直有很大的峰值电平,说话和其他声音我可以听到一点点增加,所以我需要实现一些过滤。我根本不熟悉声音处理,所以目前我没有使用任何过滤器,因为我不明白如何创建它。我当前的代码如下所示:
for(size_t i = 0; i < buffer.size(); i++)
level += abs(buffer[i]);
level /= buffer.size();
如何使用 C++ 实现这种过滤?
【问题讨论】:
“超出人类听力范围”?这是什么? 人类听不到的声音,抱歉我的英语不好,这不是我的主要语言 1) 你真正想做什么? 2)有些声音有些人能听到,但有些人不能,所以你需要更具体。 3)您显示的代码不计算峰值水平 - 它计算平均(平均)水平。 4)为什么要过滤掉无论如何都听不到的声音?它不会减少数据量或任何东西(尽管它可能会提高可压缩性,或避免混叠和进一步处理的其他问题。同样,更具体地说明您想要做什么会有所帮助)。 你应该从一些关于数字音频的书开始,你当前的代码没有多大意义 - 开始。在零背景的情况下,一本书是比问答形式更好的信息来源。 您的原始数据可能不包含很多(如果有的话)听力良好的人听不到的内容。通常引用的人类听力范围是 20Hz 到 20KHz。理论上 48KHz 采样最多可以记录 24KHz,但更快的采样主要只是简化了抗混叠滤波器的设计。 【参考方案1】:使用band pass filter。
带通滤波器是一种在一定范围内通过频率的设备 特定范围并拒绝(衰减)该范围之外的频率。
这听起来正是您正在寻找的那种过滤器。
我在 Google 上进行了快速搜索,发现 this 线程讨论了 C++ 中的实现。
【讨论】:
【参考方案2】:如果声级超过某个阈值,听起来您想做某事(可能开始录制)。这有时被称为“门”。听起来您在误报方面也遇到了麻烦。这有时通过应用于门的“侧链”来处理。
门的一般原理是创建信号的包络,然后监视包络以发现它何时超过某个阈值。如果它高于阈值,则您的门“打开”,否则,您的门“关闭”。如果您在创建包络之前以某种方式处理信号以使其对信号/噪声的各个部分或多或少敏感,则该处理称为“侧链”。
您将不得不自己发现细节,因为问答网站的内容太多了,但也许这已经足够开始了:
float[] buffer; //defined elsewhere
float HOLD = .9999 ; //there are precise ways to compute this, but experimentation might work fine
float THRESH = .7 ; //or whatever
float env = 0; //we initialize to 0, but in real code be sure to save this between runs
for(size_t i = 0; i < buffer.size(); i++)
// side-chain, if used, goes here
float b = buffer[i];
// create envelope:
float tmp = abs(b); // you could also do buffer[i] * buffer[i]
env = env * HOLD + tmp * (1-HOLD);
// threshold detection
if( env > THRESH )
//gate is "on"
else
//gate is "off"
侧链可能由 eq 等过滤器组成。这里有一个设计音频均衡器的教程:http://blog.bjornroche.com/2012/08/basic-audio-eqs.html
【讨论】:
谢谢,非常有用,目前我正在写这个sss.chaoslab.ru/git/?p=misc.git;a=blob;f=sound_detector/…,它可以工作,但是有误报,我会试试你的建议以上是关于如何使用 C++ 从 PCM 样本中过滤出超出听力范围的数据?的主要内容,如果未能解决你的问题,请参考以下文章