Python; 声音的; 检测音频信号中的静音

信息处理 声音的 Python
2022-01-18 22:59:16

我有用 python 编写的实时音频应用程序,我对检测静音有疑问。在输入音频信号中区分静音和非静音的最有效方法是什么?我所说的非沉默是指任何声音,甚至是噪音。我需要尽可能准确地知道进程中的静默期。我不一定要一些代码算法;理论提示和解释也很有用。我知道沉默的振荡水平很低(信号很平坦);numpy.fft.fft输出中,静音在 [1] bin 中具有最高幅度,依此类推,当静音存在时,有几件重要的事情。但是在代码中使用这些条件中的任何一个,都不能给我绝对准确的结果来检测静音并将其与声音完全分开。这项任务有什么先进的技术吗?

4个回答

我不会处理 python 或 numpy 或任何其他狭隘计算平台。

  1. 首先,由于“静音”是一种感知属性,因此您需要应用加权滤波器,例如A-weighting,以增强我们耳朵更敏感的音频频率分量并衰减我们不太敏感的部分。除了 A 加权之外,还有其他加权曲线。我最喜欢 Robert Wannamaker 的E-weighting

  2. 然后对滤波后的信号进行平方(以获得功率或能量)。

  3. 然后对平方和滤波后的信号进行低通滤波(以获得包络)。

  4. 然后将此包络与对应于听力阈值的阈值进行比较。

  5. 最后,您可能需要在阈值比较中加入一点滞后,以便当您的包络超过阈值时,静音/非静音结果不会抖动。

这类似于压缩器/限制器/门过程中的“门”功能,有时会在音频应用程序中找到表达。“门”是为了确保在“沉默”时间段内,被认为是沉默的东西(或足够低的水平,应该被认为是沉默)变为零。

Pythonlibrosa库具有您可以使用的功能:

librosa.effects.split(y=buffer, frame_length=8000, top_db=40)

将音频信号拆分为非静音间隔。
给定 8000 的采样率,它将通过在 1 秒内检测低于 40db 的音频来分割音频

或者,您可以使用以下方法修剪音频“静音部分”:

librosa.effects.trim(y=buffer, frame_length=8000, top_db=40)

我需要类似的东西,将大型 WAV 文件拆分成块,静音时间超过一定长度。所以我写了这个随意使用它。

它使用内存映射输入文件scipy.io.wavfile.read(..., mmap=True)(因为我的 WAV 文件大于我的可用 RAM),然后使用生成器来处理它。这意味着,您可以轻松地将其调整为传入的实时音频流。

该算法不像@robert-bristow-johnson 建议的那样优雅,但它应该更快,并且适用于任意大的文件。它将输入文件分割成等长的重叠窗口,计算每个窗口的能量,并确定每个窗口的能量是高于还是低于某个阈值。

我还使用tqdm包含了一个进度条,如果您正在处理不定长度的输入流,则应该将其删除。

您不会为您的问题找到“绝对正确”的方法。

我喜欢罗伯特的方法。我要在他的方法中添加的一件事是将输入音频的电平调整到预定值(比如 65 dB SPL),以便在他提供的其余处理步骤之前建立一个固定电平。这将消除音频电平的可能变化并帮助设置步骤 4 中提到的阈值。您可能还需要进行几次听力测试以帮助设置合理的阈值。