Web Audio API 第3章 音量和响度
此章介绍的科普物理声音知识相当有用,编程的反而涉及的少
音量和响度
Loudness 响度 注:根据《韦氏词典》,响度是“一种声音的属性,它决定了所产生的听觉感觉的大小,主要取决于所涉及声波的振幅。”这意味着响度取决于你大脑中感知到的声音。而是声音对你来说有多大。这是主观的——例如,对你来说很响的声音对有听力问题的人来说可能听不到
Volume 音量 注:我们通常用在收音机、电视、立体声或其他乐器上。你可以用控制按钮或滑块来控制响度。即使响度仍然是基于你的感知,乐器也可以以不同的水平播放音频
一旦我们准备与声音打交道,无论是 AudioBuffer 还是其它来源的声音,最基本的可控参数就是声音的响度
最主要可以影响音量响度的方式就是使用 GainNode。正如之前提到过的,音频节点都有一个 gain 参数,作为声音输入缓冲的乘数。默认值是 1,意为着没有任何影响。值从 0 至 1,如果值超过了 1 则放大了输入声音的响度。将 gain 值设为负值(值小于0) 则波形反转(幅度翻转了)。
重要理论: 音量(Volume),增益(Gain) 和响度(Loudness)
让我们从它们的定义开始。响度是我们耳朵理解声音的主观衡量。音量是从物理声波振幅来衡量。增益则是处理声波过程中对其波形振幅乘数缩放。
换句话来说,增益时一个声音波形的振幅乘以增益乘数后被缩放了。举个例子,当值为 1 时不影响声音波形,图 3-1 图示了当声音波形通过增益值为2的节点后的结果

图 3-1 左侧是原波形,右侧是增益2后的波形
一般来说,波的功率以分贝(decibels, 缩写为dB)或贝尔的十分之一来测量,贝尔以亚历山大·格雷厄姆·贝尔命名。分贝是相对的,将被测量的等级与某个参考点进行比较的对数单位。有多种不同的参考点用于测试分贝,每一种参考点都有着指示前缀单位。没有参考点说信号的分贝是无意义的!举个例子,dBV, dBu, 和 dBm 都是非常有用的衡量电信号方式。由于我们仅关心数字音频,我们主要关心两种测量方式: dBFS 和 dBSPL
第一种 dBFS (decibels full scale) .音频设备产生的最高声级是0 dBFS。** 所有其他级别都以负数表示 **.
dBFS 的数学描述如下:
dBFS = 20 * log( [sample level] / [max level] )
dBFS 最大值 在 16位音频系统中:
max = 20 * log(1111 1111 1111 1111/1111 1111 1111 1111) = log(1) = 0
注意,dBFS 由定义可得最大值总是为 0
最小 dBFS 值在类似的系统中是:
min = 20 * log(0000 0000 0000 0001/1111 1111 1111 1111) = -96 dBFS
** dBFS 衡量的是增益而非音量。** 你可以试试 0-dBFS 将立体声节点增益设为最小值,这样应该几乎就听不到了。相反如果是 −30-dBFS这样的低音量,如果设一个最大的增益值,那么依然可能将你的耳膜吹破。
尽管如此,你还是很可能听到有人跟你用分贝来描述用音量。从技术上讲,他们指的是dBSPL,(decibels relative to sound pressure level)即分贝相对声压等级的。这里,参考点是每平方米0.000002牛顿(大约是蚊子在3米外飞行的声音)。dBSPL 没有上限,但在实践中,我们希望保持在耳朵损伤水平(~120 dBSPL)以下,远低于疼痛阈值(~150 dBSPL)。Web Audio API 不使用 dBSPL,只使用 dBFS 这是因为最终音量取决于操作系统的增益和杨声器的增益。
分贝的对数定义在某种程度上与我们的耳朵感知声响的方式有关, 但响度依然是时分主观的概念。将一个声音的dB值与具有2倍增益的相同声音进行比较,我们可以看到差值大约是 6dB
diff = 20 * log(2/2^16) - 20 * log(1/2^16) = 6.02 dB
每次增加 6dB 左右,我们实际是对信号放大了双倍。对比摇滚音乐会(~110 dBSPL) 与你的闹钟(~80 dBSPL), 两者之差是 (110 − 80)/6 dB,或大概是5倍大小,即增益乘数2^5 = 32倍。立体音响的旋钮音量调节也是标准的指数增幅。也就是说音量旋钮转3个刻度单位意即音信号增大2的3次方也就是8倍。在此用指数模型描述仅仅是近似我们人耳认知的声响,而音响生产商一般都有自己的定制化增益曲线它即不是线性也不是指数形。
注:人耳对舒适声音的范围一般在20-40分贝之间,犹如轻声絮语。一般情况下,人体所能承受的音量是在80分贝以下,如果长期在80分贝以上的环境生活,就会出现头痛,记忆力衰减以致失眠等症状。当人耳听到的音量达100分贝时,时间较长可造成不可恢复性的听力损伤;长时间受120分贝以上音量的刺激,听觉细胞就会受到永久性的破坏,严重者还会造成听力丧失。
等功率交叉渐变(crossfade)
在游戏开发中,你会遇到一种情况,就是在两个拥有不同声音的环境中交叉渐变(crossfade), 然而什么时候渐变,渐变多少不是提前已知的; 很有可能是根据玩家的位置而变化的,这取决于玩家对角色的控制位置。所以在这种情况下,我们无法做到自动计算。
通常,直接进行线性渐变会得到以下图。它可能听起来不平衡,因为两个样本之间的音量下降,如图 3-2

图 3-2 两条音轨的线性交叉渐变
为了解决这种情况,我们使用等功率曲线,其中相应的增益曲线既不是线性的也不是指数的,它会在更高的振幅处相交图 3-3 。这有助于当两个声音均匀地混合在一起时避免在交叉渐变的中间部分音量下降。

图 3-3 等功率曲线线性交叉渐变要好的多
图 3-3 用一点点数学就能搞定:
function equalPowerCrossfade(percent) {
// Use an equal-power crossfading curve:
var gain1 = Math.cos(percent * 0.5*Math.PI);
var gain2 = Math.cos((1.0 - percent) * 0.5*Math.PI);
this.ctl1.gainNode.gain.value = gain1;
this.ctl2.gainNode.gain.value = gain2;
}
重要理论: 裁剪和计量
就像图片边界超过 canvas ,声音波形如果超出最大值限制也可以被裁剪。这种显著的失真肯定是不能接受的。为了不让工程师和用户感知处理音频时不被裁剪,音箱设备通常会提供指示器显示音频数值等级。这些指示器被称为 meters (图 3-4),它通常有一个绿色区域(不裁剪),黄色区域(接近裁剪区),红色区(裁剪)。

图 3-4
被裁剪的声音看起来和听起来都不太好。重要的是要听刺耳的失真,或者相反,过度柔和的混音,迫使你的听众调大音量。如果你处于以上任何一种情况,请继续往下读
使用仪表检测与阻止裁剪
由于同时播放的多个声音是叠加的,这些声音音量没有降低级别,你可能会发现自己处于超出扬声器能力阈值的情况。16位的音频音量最高级 是 0 dBFS, 或 216。在信号的浮点数版本中,这些比特值都映射到了 [-1, 1]. 声音的波形被裁剪看起来像是图 3-5, 在 Web Audio API 上下文中,传递给目的节点(destination node)值如果超过了目的节点设备的范围则会发生裁剪。给最后混音留出一些空间(称为 headroom) 的做法就很好,这样你就不会太接近裁剪阈值了。

图 3-5 波形被裁剪的示意图
除了仔细聆听之外,您还可以通过将脚本处理器节点放入音频图中来检查是否以编程方式截取声音。如果任何 PCM 值超出可接受范围,可能会发生剪切。在这个示例中,我们检查左通道和右通道的裁剪,如果检测到裁剪,则保存最后的裁剪时间:
function onProcess(e) {
var leftBuffer = e.inputBuffer.getChannelData(0);
var rightBuffer = e.inputBuffer.getChannelData(1);
checkClipping(leftBuffer);
checkClipping(rightBuffer);
}
function checkClipping(buffer) {
var isClipping = false;
// 检测循环迭代 buffer 是否超出值 1
for (var i = 0; i < buffer.length; i++) {
var absValue = Math.abs(buffer[i]);
if (absValue >= 1.0) {
isClipping = true;
break;
}
}
this.isClipping = isClipping;
if (isClipping) {
lastClipTime = new Date();
}
}
测量的另一种实现方式是在音频图内轮询一个实时解析器,在渲染时为 getFloatFrequencyData,它取决于 requestAnimationFrame 方法(见第5章)。这种方式更高效,但信号丢失的比较多(包含用于可能裁剪的空间位置),由于渲染大多是每秒 60次,而音频信号相对变化的更快
阻止裁剪的方式是降低信号总电平。如果您正在进行音频剪辑,请在主音频增益节点上应用一些分数增益,以使您的混音降低到阻止裁剪。一般来说,你应该调整增益来预测最坏的情况, 但把它调的更好则是一种艺术而非科学的事儿了。由于游戏或交互式应用程序中播放的声音可能取决于运行时决定的各种因素,因此很难在所有情况下选择阻止裁剪的主增益节点值。对于这种不可预测的情况,请考虑动态压缩( Dynamics Compression )
重要理论: 理解动态范围
动态范围:音频或广播系统能够传输或重现的最强和最弱声音强度之比, 具体来说,最强声音强度指的是系统能够产生或传输的最大响度或音量,而最弱声音强度则指系统能够检测或重现的最小响度或音量。这个比例反映了系统在声音强度方面的表现力和分辨率。
较高的声音强度之比意味着系统能够呈现出更明显的音量差异,从而提供更丰富的音频细节和动态范围。例如,一个具有较大声音强度之比的系统可以更好地表现出轻柔的声音和强烈的声音,使听众能够感受到更广阔的音频频谱和更强的音频冲击力。
相反,较小的声音强度之比可能意味着系统在处理音量差异方面的能力较弱,可能会导致一些细节丢失或音频表现力的受限。
在音频领域,动态范围是声音的最高音与最低音的之间的部分。音乐作品的动态范围因流派而异。经典音乐拥有大的动态范围并且有非常安静的部分常伴有跟着的相关的响亮部分。而流行音乐如摇滚和电子乐则倾向于小的动态范围,并且由于明显的竞争(被蔑称为“响度战争”)来提高音高以满足消费者的需求,所以声音都很响。这种均匀的响度通常是通过使用动态范围压缩来实现的。
有多种合理的动态压缩手段可用。有时候录制的音乐有一个大的动态范围,其中有非常高和非常低的片段以至于听者需要不断用手指调节音量旋钮。压缩可以使大声的部分安静下来,同时使安静下来的部分可以被听到 图 3-6 展示了波形上图是正常波形图下图是压缩后的。你可以看到声音都变大了,且振幅差异也小了。

在游戏和交互式应用中,你可能事先不知道你的声音输出会是什么样子。由于游戏天然的动态性,你可能需要在一个非常安静的音频周期(比如,鬼鬼祟祟的溜)后跟一个高音(比如,游戏《使命召唤:战争地带》)。一个压缩节点对需要处理声音突然变高音的情况下下非常有用,可以降低被裁剪的可能性。
压缩器可以用包含多个参数的压缩曲线来建模,所有这些参数都可以通过 Web Audio API 进行调整。两个主要的的可调参数是 threshold 和 ratio。Threshold 阈值是指压缩器 开始减小动态范围的最低音量。ratio 比率决定了压缩器应用多少增益降低。图 3-7 阐述了阈值与变化的压缩比率在压缩曲线上的影响效果。

动态压缩
压缩器在 Web Audio API 中也能使用被叫做 DynamicsCompressorNodes。使用温和的动态压缩量在混音中是比较好的做法,特别是在我们之讨论过的在不知道何时何地播放声音游戏设置中。有一种情况下应该避免使用压缩,那就是在曲目被故意设计成这样,因为已经被精确调好,它不应该再和其它通道混合了。
在 Web Audio API 内实现动态压缩比较简单,只要在音频图内引入一个动态压缩器节点,一般就是在目标节点之前:
var compressor = context.createDynamicsCompressor();
mix.connect(compressor);
compressor.connect(context.destination);
此节点还可以被配置一些额外的参数,正如描述过的理论章节中所述,但对于大多数情况默认值已经相当棒。更多关于压缩曲线的配置信息,可以查看 Web Audio API 说明书
注:转载请注明出处博客园:王二狗Sheldon池中物 (willian12345@126.com)
Web Audio API 第3章 音量和响度的更多相关文章
- H5的Web Audio Api
概述 研究Web Audio Api的主要原因是:工作中需要在ios中实现声音的淡出效果,主要是通过setInterval来改audio标签的volume属性实现的,但是ios上面volume属性是只 ...
- HTML5 ——web audio API 音乐可视化(一)
使用Web Audio API可以对音频进行分析和操作,最终实现一个音频可视化程序. 最终效果请戳这里; 完整版代码请戳这里,如果还看得过眼,请给一个start⭐ 一.API AudioContext ...
- 【HTML5】Web Audio API打造超炫的音乐可视化效果
HTML5真是太多炫酷的东西了,其中Web Audio API算一个,琢磨着弄了个音乐可视化的demo,先上效果图: 项目演示:别说话,点我! 源码已经挂到github上了,有兴趣的同学也可以去st ...
- 关于HTML5音频——audio标签和Web Audio API各平台浏览器的支持情况
对比audio标签 和 Web Audio API 各平台浏览器的支持情况: audio element Web Audio API desktop browsers Chrome 14 Yes ...
- [Javascript] Intro to the Web Audio API
An introduction to the Web Audio API. In this lesson, we cover creating an audio context and an osci ...
- 关于Web Audio API的入门
Web Audio API提供了一个简单强大的机制来实现控制web应用程序的音频内容.它允许你开发复杂的混音,音效,平移以及更多. 可以先看一下MDN的这篇文章<Web Audio API的运用 ...
- 使用Web Audio API绘制音波图
摘要:Web Audio API是对<audio> 标签功能上的补充,我们可以用它完成混音.音效.平移等各种复杂的音频处理,本文简单的使用其完成音波图的绘制. PS:本例子使用ES6编程, ...
- Web Audio API之手把手教你用web api处理声音信号:可视化音乐demo
1.Web Audio API 介绍 Web Audio API 提供了在Web上控制音频的一个非常有效通用的系统 ,这些通用系统通俗的讲就是我们可以利用Web Audio API提供的各种方法操作各 ...
- HTML5 ——web audio API 音乐可视化(二)
上一篇 web audio API 音乐可视化(一)介绍了一些基本的API,以及如何简单的播放一个音频,本篇介绍一下怎么对获取到的音频进行分析,并将分析后的数据绘制成图像. 最终效果请戳这里; 完整版 ...
- 【Web Audio API】 — 那些年的 web audio
转 TAT.Jdo:[Web Audio API] - 那些年的 web audio 这主题主要是早期对 web audio api的一些尝试,这里整理一下以便以后翻阅,如有错误,诚请指正. 在这之前 ...
随机推荐
- jar not loaded. See Servlet Spec 3.0, section 10.7.2 Offending class: javax/servlet/Servlet
说明: 今天在整合activemq功能时启动应用模块报错: jar not loaded. See Servlet Spec 3.0, section 10.7.2 Offending class: ...
- win32编辑控件字体
每次到用的时候就各种查资料,我这人记性又不好,遂记录下来: 普通的编辑控件: 创建:HWND hText = CreateWindowW(L"EDIT", L"enter ...
- RK3568开发笔记(三):RK3568虚拟机基础环境搭建之更新源、安装网络工具、串口调试、网络连接、文件传输、安装vscode和samba共享服务
前言 开始搭建RK3568的基础虚拟机,具备基本的通用功能,主要包含了串口工具minicom,远程登陆ssh,远程传输filezilla,代码编辑工具vscode. 虚拟机 文档对对虚拟机 ...
- 使用俩个链接在一起的容器运行wordpress
# 问题,如何分离mysql和wordpress,使它们每个都单独运行一个容器. # 解决办法:运行时通过--link选项使它们链接在一起 --link <container_name>: ...
- ASP.NET 读取FTP文件流
参考资料 ASP.NET 上传文件到共享文件夹 工具类代码 /// <summary> /// 读取ftp文件流 /// </summary> /// <param na ...
- 【图论#02】岛屿系列题(数量、周长、最大面积),flood fill算法的代码实现与优化
岛屿数量 给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量. 岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成. 此外,你可以假设该网 ...
- 【Azure Redis】Redis-CLI连接Redis 6380端口始终遇见 I/O Error
问题描述 使用Redis-cli连接Redis服务,因为工具无法直接支持TLS 6380端口连接,所以需要使用 stunnel 配置TLS/SSL服务.根据文章(Linux VM使用6380端口(SS ...
- 【Azure 事件中心】EventHub 中同一条消息不停的推送给消费端问题记录
问题描述 EventHub 中同一条消息,不停的推送给消费端,查看日志发现错误: Caused by: com.azure.messaging.eventhubs.implementation.Par ...
- 固态硬盘使用f2fs作为根分区安装linux
目录 前言 碰到的问题 对策 我的实际操作步骤 0.警告 1. 准备 2. 分区 3. 使用网络安装debian10 4. 备份根分区 5. 修改固态硬盘linux根分区为f2fs 6.恢复备份 7. ...
- python 字典列表,元组列表 列表嵌套字典 列表嵌套元组 字典嵌套列表
列表嵌套字典 l=[] for i in alist: kk = {} names.append(i.string) a_url.append(i.get('href')) kk['章节名']=i.s ...