Skip to content

Latest commit

 

History

History
221 lines (140 loc) · 12.1 KB

README_zh.md

File metadata and controls

221 lines (140 loc) · 12.1 KB

License GitHub Release Downloads



Praditor_icon

Praditor

基于DBSCAN聚类的自动语音起始点检测器

下载 Praditor | English · 中文


特点

作为语音起始检测器, Praditor可以帮助你自动地找到所有的有声无声的边界。

audio2textgrid.png

Praditor可以处理单起始点多起始点音频文件,无论你的音频文件是什么语言。

  • 起始点/结束点检测
  • 有声/无声检测

Praditor计算得出的起始点会以.TextGrid的PointTier呈现,并允许用户调整参数以获得更好的结果。

作者

我是澳门大学认知与脑科学中心的Tony,Praditor的编写者。 研究方向是心理语言学(Psycholinguistics),对,写Python是业余的XD。我喜欢把繁琐复杂的流程转化为标准化的脚本,懒惰(某种意义上)是我的第一生产力。

Praditor是一个帮助语音研究方向的科研人节省时间的项目。它基于简单粗暴但又十分有效的阈值法(再加上一点点平滑和降噪),让你能够一个人在几分钟内得到好几个人标注数个星期的工作成果。 写这个软件的初衷是:科研工作者需要投资时间的地方是思考实验设计/分析数据;这种繁琐、重复、枯燥的重复劳动应当交给编程来解放你。

因为Praditor的给出的结果文件是PointTier,而PointTier通常不好操作。如果你需要一些后续脚本

  • 导出单个音频文件
  • 导出时间戳为表格文件(e.g., .xlsx, .csv)
  • 其他需求

或者,单纯想知道如何使用Praditor/Praditor是如何实现检测算法的,欢迎联系我的邮箱 [email protected][email protected]。 目前Praditor正在测试阶段,欢迎大家传播、分享、合作!

我们准备了测试音频,您可以通过它来熟练操作。

如何使用Praditor?

1. 导出音频

File -> Read files... -> 选择目标音频文件

import_audio.png

2. 使用Praditor

gui.png

对于起始点/终止点...

  • Run 应用 Praditor 算法于当前音频
  • Prev/Next 上一个/下一个音频
  • Read 从当前音频的.TextGrid结果文件里读取时间戳
  • Clear 清除已显示的时间戳
  • Onset/Offset 显示/隐藏起始点/终止点

对于参数...

  • Current/Default 显示默认/当前参数(即,独属于当前文件的参数)
  • Save 把仪表盘显示的参数保存为默认/当前参数
  • Reset 重置参数(清除显示的参数,并显示已保存的默认/当前参数)

对于菜单...

  • File > Read files... > 选择音频文件
  • Help > Parameters > 显示如何调整参数的快速指导

如果你想要放大/缩小视图

  • 滚轮 ↑/滚轮 ↓时间线上放大/缩小
  • Ctrl+滚轮 ↑/滚轮 ↓波幅上放大/缩小 (针对 Windows 用户)
  • Command+滚轮 ↑/滚轮 ↓波幅上放大/缩小 (针对 Mac 用户)

快速了解 Praditor 算法

音频信号首先经过带通滤波降噪,以滤除高频/低频的噪声。然后,音频信号会进行最大池化 (max-pooling)降采样 (down sampling), 即用最大值来代表每一个区块。

ds_maxp.png

DBSCAN需要数据集具有两个维度,而音频信号是一维的时序信号。我们应该如何把一维的音频信号转化为二维的数组? 我们试着把每两个连续的(降采样)区块组合成一个,那么,这个就具有了两个维度(前一帧,后一帧)。

根据这样的转换逻辑,我们得到了一个音频信号的二维点阵。 接着,Praditor 将 DBSCAN 聚类算法应用于这个点阵,并成功地将靠近原点的噪声点聚集(因为噪声点的振幅通常较小)。

DBSCAN_small.png

到了这个阶段,我们已经找到了所有的噪声区域——可能存在起始点的目标区域已经大致定位到了(即,噪声区域的边缘)。 然后,我们将对信号求导,得到音频信号的一阶导。一阶导阈值法是一种常见的信号处理手段(例如,心电 ECG),可以用于平滑信号/降噪。 求导的操作使得信号的趋势得以保留,去除了毛糙的部分。这对阈值法的表现的提升十分重要。

scan.png

对于每一个目标区域,我们重复以下之流程:

  1. 设置一个噪声参考区域。该段信号的一阶导的绝对值的均值将作为基线。
  2. 从参考区域的下一帧开始,逐一作为开始帧(starting frame),也就是起始点候选
  3. 从开始帧开始,往后逐帧扫描。Praditor 使用核平滑(kernel smoothing) 的方法来检查当前帧(或者说,当前核/时间窗)是有效的/无效的
  4. 当我们得到了足够的有效帧,此时的开始帧/时间戳即我们想要的起始点(onset);否则,我们进入到下一个开始帧的验证。

参数

HighPass/LowPass

在开始对音频信号进行降采样+聚类之前,我们首先对于原始信号进行带通滤波。原因是,其实我们并不需要这么完整的频段,太高或者太低的频段可能被污染。

choose_freq.png

我们需要的其实就是中间这部分频段,无声有声对比度最大

这两个参数较少需要调整。 请注意,参数 LowPass不可以超过该音频的最高有效频率,即采样率的一半(具体原理请参考奈奎斯特定理)。

EPS%

DBSCAN 聚类需要两个参数:EPSMinPt。 DBSCAN 的聚类逻辑是:检查每一个点,以该点为圆心,EPS 为半径画圆。如果这个圆里有足够多数量的点(即,达到MinPt),那么这些点都属于同一个簇(cluster)。

DBSCAN.png

这两个参数较少需要调整。 Praditor 允许用户调整 EPS%。该参数的运作逻辑是:每一个音频的振幅变动范围都是不一样的。我们根据每一个音频的最大波幅,乘以一个百分比 EPS%, 得到了最终可以放入DBSCAN的 EPS 参数。

RefLen

当 Praditor 确认了目标区域的时间,我们不再使用原始的波幅,而是将其求导并绝对值化,得到音频信号一阶导的绝对值。 这个操作被称作一阶导数阈值法(First Derivative Thresholding).

对于每一个目标区域,Praditor会设置一个参考区域。这个区域通常位于噪声区,其均值将被作为阈值法的基线;而该区域的长度由参数 RefLen 决定。

reflen.png

针对 RefLen 的调参建议是:如果需要捕捉较小长度的静音段(例如几百毫秒),你需要考虑调小 RefLen 以使其不超过静音段的长度。 当然,我的经验是通常你不太需要动这个参数。

Threshold

这是最常用的参数。 阈值法的核心概念可以看作是“击中断崖(Hitting the cliff)”。说话者说话会使得音频信号的波幅(或是其他信号特征的数值)上升,就像是创造了一个“断崖”。

threshold_possibly_close.png

Threshold 的最小值限制在1.00(相对于噪声参考区域的基线值)。录制到的说话声应当大于背景噪声——信号的波幅应当大于噪声参考的波幅。 然而,背景噪声通常不是“平滑的”,而是“毛糙的”;也就是,基线值通常小于毛糙部分的顶点(因为基线值是平均得来的)。 所以,实际情况是 Threshold 应当稍微大于1.00(永远不会等于1.00,这就违背了最基础的假设“说话声大于噪声”)。

asp_sound.png

同时,我会建议你着重关注 送气音。当一个单词以送气音开头,它并不形成一个 “断崖(cliff)” ,而是一个 “缓坡(very slow slope)” —— 这种差异导致了正常情况击中“断崖”而落下得到的起始点,会停留在“缓坡”的半坡上。 当送气音被斩断,音频会听起来像是“突然爆炸(burst)”, 有一种突兀感;而非完整截取时得到的渐进。

KernelSize, KernelFrm%

在设定好阈值参考基线之后,Praditor 将会(1)设置一个开始帧;(2)从开始帧开始,往后逐帧扫描。 这个流程会重复,直到我们找到了一个有效开始帧

具体的,“逐帧扫描”指的是,把这一帧的数值(即一阶导的绝对值)和阈值进行对比。如果在阈值之上,我们便称其为“有效”;反之则“无效”。

Praditor的算法略有不同,我们加入了 核平滑(kernel smoothing) 的操作,即在扫描的过程中,从被扫描帧后续的帧中借取信息—— 我们会设立一个大小为 KernelSize 的时间窗, 并平均时间窗内的值;也就是说,“逐帧扫描”的对象是时间窗的平均值。

kernel.png

在“逐帧扫描”的过程中,为了防止极端值,Praditor会忽略掉最大的几个值。反过来说,我们会保存这个时间窗/核内 KernelFrm% 部分数量的值(比如,80%)。 如果真的有极端值存在,那么这个操作就成功避免掉了它们的影响;如果极端值不存在,也无伤大雅,因为它们和其他值很接近。

CountValid, Penalty

我们如何定义起始点?在该时间点之后,连续的有很多帧都高于阈值。

正如上面提到的,确认了开始帧后,Praditor会逐帧扫描(逐窗/核扫描),其结果无非是高于低于阈值。 如果高于阈值,则称作有效,计为 +1;如果低于阈值,则称作无效,计为 -1 * Penalty

在扫描的过程中,我们实时地累计、求和这些值,得到一个动态的扫描和(scanning sum)。 当扫描和小于等于0时,扫描中止,我们转入下一个 开始帧 (换句话说,我们只想要一个扫描和保持为正数的开始帧)。

在这里,Penalty 像是一个调节 噪声灵敏度 的“旋钮”。Penalty 调的越高,对低于阈值的帧越敏感——越强调“连续性地大于阈值”的要求。

count_valid.png

总结来说,每次扫描都有一个开始帧(即,起始点的候选)。扫描的目的是:验证这个开始帧是否有效。 有效的标准是,扫描和保持为正数,直到其最终达到标准 CountValid。由此,该开始帧便可以认定为是起始点

这样的设定能够帮助我们忽略背景噪声中短暂但波幅极高的噪声。此类噪声通常是短促的,且并不和真正的说话声连接;只要它在正式说话之前消停了

材料和数据

如果你想要下载我们用于开发和测试 Praditor 的音频数据,可以参考 我们的 OSF 仓库