检测音频包络开始和停止位置的最简单方法


43

以下是代表某人讲话记录的信号。我想基于此创建一系列较小的音频信号。想法是检测“重要”声音的开始和结束时间,并将其用作标记,以制作新的音频片段。换句话说,我想将静音用作指示音频“块”何时开始或停止的指标,并以此为基础创建新的音频缓冲区。

例如,如果某人记录自己说

Hi [some silence] My name is Bob [some silence] How are you?

那么我想从中制作三个音频片段。一个说Hi,一个说My name is Bob,一个说How are you?

我最初的想法是通过音频缓冲区不断检查是否存在低振幅区域。也许我可以通过获取前十个样本来进行此操作,取平均值,如果结果很低,则将其标记为无声。我将通过检查接下来的十个样本来继续处理缓冲区。通过这种方式递增,我可以检测到信封的开始和停止位置。

如果有人对好的,简单的方法有任何建议,那就太好了。就我的目的而言,解决方案可能是非常基本的。

我不是DSP的专业人士,但了解一些基本概念。另外,我将以编程方式进行此操作,因此最好讨论算法和数字样本。

感谢您的所有帮助!

在此处输入图片说明


编辑1

到目前为止反应良好!只是想澄清一下,这不是实时音频,我将自己用C或Objective-C编写算法,因此使用库的任何解决方案都不是真正的选择。


1
听起来您正在尝试使用无声的时间将其分解为中断点。为什么不只使用功率阈值确定“沉默”,又有阈值时间来确定它是否足够长以构成中断?
Jim Clay 2012年

@JimClay是的,这正是我想要做的。我从未听说过功率阈值,但这听起来像是我可以使用的东西。复杂吗?您能对此进行扩展吗?
埃里克·布鲁克托

@EricBrotto也许您应该向我们介绍一下您的库中具有哪些功能。这将使我们能够更好地为您按摩实际方法。
Spacey 2012年

这种沉默检测的方法更好?应将阈值级别设置为0.05 x = wavread('s1.wav')以外的值;i = 1;而abs(x(i))<0.05%沉默检测i = i + 1;结束x(1:i)= []; x(6000:10000)= 0;
zeee 2014年

Answers:


26

这是语音检测的经典问题。首先要做的就是使用Google的概念。它已广泛用于数字通信中,并且对此主题进行了很多研究,并且有不错的论文。

通常,必须处理的背景噪声越多,语音检测方法就必须越复杂。如果您使用的是在安静的房间中拍摄的录音,则可以轻松完成(以后再做)。如果您在别人讲话时有各种各样的声音(卡车经过,狗叫,碎片砸碎,外星人发动攻击),则您必须使用一些更聪明的方法。

查看您附加的波形,您的噪声很小,因此我建议以下几点:

  1. 提取信号包络
  2. 选择一个好的门槛
  3. 检测包络幅度超过阈值的地方

这是什么意思呢?信号的包络线是描述其幅度随时间变化的曲线,与信号的频率成分如何振荡无关(请参见下图)。

在此处输入图片说明

{1,45,6,2,43,2}{1,45,6,2,43,2} 可以通过实验找到,并且可能取决于多种因素,例如采样率。

您可以从图像中看到没有太多的噪声,信号包络将始终高于某个阈值(响度级别),并且可以将这些区域视为语音检测区域。


3
我实际上已经将它实现为good'ol winamp的插件之一。您所描述的是好的,但还不够。通常有浊音(元音)和清音(辅音)。如果只有语音声音,那么您所描述的内容就可以使用-但非语音声音的能量非常低,与一般的噪音很难区分开。而且即使在演播室中,无噪音条件也非常罕见。
Dipan Mehta 2012年

如何在python中实现呢?
kRazzy R

26

实际上,您真正想要做的是称为“ 语音活动检测”或“语音检测”。

基本上,任何纯语音信号(不包含音乐)都包含三个部分。

  1. 浊音-基本上是由元音引起的
  2. 清音-包含辅音。

人类声音的特征是,尽管在浊声中使用了大量能量,但真实信息却包含在辅音中。同样,浊音通常是较低频率,而清浊音是较高频率。[确切地说,对于给定的人,所有浊音或多或少地以恒定频率共振,这是他/她的音调]。

现在,任何系统都存在噪音。浊音通常足够强大,可以将其清晰可见。当您应用较低频率的过滤时,可能会收集到足够数量的浊音,但是清音(包含所有丰富的信息)将会丢失。

出现问题如何解决:

诀窍在于,清音仍然来自共振声源。并固有地受到一定频率的限制。那里的噪音相当均匀。因此,将这三个特征区分开的简单方法是“局部功率”,或者等效的方法是采用窗口自相关。

如果您一次要说100个样本-并自动进行自我关联,则如果仅包含噪声,结果将几乎为零(这是白噪声的属性),而对于语音信号,此幅度将是可观察到的,因为该信号仍然有更好的结构。过去这对我有用。

VAD一直是活跃的研究领域-因为几乎所有的移动电话通信都希望检测非语音部分并将其从编码中删除。但是,如果他们删除无声音的语音,这将使电话无用。

G.729标准基于以下特性来计算VAD:线频谱频率,全频带能量,低频带能量(<1 kHz)和过零率。

GSM标准的工作方式如下:选项1计算九个频段的SNR,并将阈值应用于这些值。选项2计算不同的参数:信道功率,语音度量和噪声功率。然后,它使用根据估计的SNR变化的阈值对语音指标进行阈值设置。(来自维基百科)

对于更高级的技术,我列出了有关此主题的一些参考。

  1. 最常出现的参考文献:Jongseo Sohn;南秀金;Wonyong Sung;“基于统计模型的语音活动检测”,信号处理快报,IEEE,1999年1月,第6卷:1 pp:1-3

  2. 与您最相关:Mark Marzinzik和Birger Kollmeier,“通过跟踪功率包络动态来进行语音暂停检测,以进行噪声频谱估计”,IEEE语音和音频处理事务,VOL。10号 2002年2月2日,第109页

  3. 拉米雷斯,J。JMGórriz,JC Segura(2007年)。“语音活动检测。基本原理和语音识别系统的鲁棒性”。在M. Grimm和K. Kroschel中。强大的语音识别和理解能力。1-22页。ISBN 978-3-902613-08-0。

  4. 简介:乔纳森·科拉(Jonathan Kola),卡罗尔·埃斯皮·威尔逊(Carol Espy-Wilson)和塔伦·普鲁西(Tarun Pruthi)“语音活动检测”


如何在python中实现呢?
kRazzy R

9

我会完全赞同吉姆·克莱(Jim Clay)的观点,但会使用信封略微改变口味:

我们知道语音主要出现在1-2kHz左右。您的数据采样可能为44kHz(这取决于您的记录设备)。因此,我首先要做的是在10个点上实时对平方信号进行移动平均,以得到信号功率的包络线。这将导致检测延迟,因此您希望将其保持在较低水平。

然后,我将在您的系统上添加一个校准阶段:让用户保持沉默,按下按钮,并记录背景噪音(例如10秒钟)。取包络线的平均幅度或中值幅度乘以2即可得到安全,这将自动为您提供Jim一直在谈论的阈值。

如果不是实时录制,您可能会发现使用0相移动平均值来减少由延迟引起的烦恼。告诉我们它是否对您有效。


9

埃里克

如果您确实想要快速而肮脏的东西,那么您首先需要得到的就是信封,而我可以通过以下方式(在MATLAB中)简单地做到这一点:

 envelope = abs(hilbert(yourSignal));

在这一点上,我只是简单地设置阈值,如果您超过某个阈值,则“声音存在”。

顺便说一句,这是一个非常简单的解决方案,但它可能对您有用。


1
+1。也许您可以详细说明此代码行背后的方法?我确定OP对通过希尔伯特变换进行包络提取不熟悉。
声子

@穆罕默德谢谢!但是,请参阅我的编辑1。我当然想快速又肮脏,但是我自己也需要做算法:)
Eric Brotto 2012年

@EricBrotto好的,我可以告诉您如何实现希尔伯特转换器,但是我假设您有能力在C / Obj-C库中执行FFT?如果不是这样,那将是一个问题... :-)
Spacey 2012年

如何在python中实现呢?
kRazzy R

亲爱的先生/女士,您能否指出我关于如何在Python中实现该希尔伯特的资源?
kRazzy R

6

我假设您正在处理真实的而不是复杂的信号-如果不是这种情况,请告诉我,我可以修改答案。

功率定义为信号的平方(即信号样本乘以自身)。您可以将功率与某个阈值进行比较,以确定是否存在语音。您可能需要对录音进行一些测量,以凭经验找到合适的阈值。

如果您的录音是“干净的”(即没有太多噪音),我可能会通过将瞬时功率(即单个样本)与阈值进行比较来尽可能地简化。这意味着,即使您不想对它进行平方运算,也只需要绝对值并将其与功率阈值的平方根进行比较即可。当您检测到语音时,先抓住它并进行一些录音,以确保获得全部语音(也许是1/10秒)。继续进行下去,直到发现长时间没有样品超过阈值为止。再次,周期的长度将需要根据经验确定。

冲洗并重复。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.