音频可视化中的信号处理方案
栏目: JavaScript · 发布时间: 5年前
内容简介:音频可视化是一个“听”起来非常“美”好的话题,其复杂程度很大程度上依赖视觉方案(不管你选用什么渲染方案,处理音频信号部分是相通的,本文会围绕音频信号的处理进行阐述,期望能够给大家普及一下音频相关的基础知识(由于能力所限难免疏错,欢迎指出)。
声明: 原创文章,未经允许不得转载。
音频可视化是一个“听”起来非常“美”好的话题,其复杂程度很大程度上依赖视觉方案( 一些例子 ),不同的视觉方案决定了你的技术方案选型,比如 three.js , pixi.js 等引擎。
不管你选用什么渲染方案,处理音频信号部分是相通的,本文会围绕音频信号的处理进行阐述,期望能够给大家普及一下音频相关的基础知识(由于能力所限难免疏错,欢迎指出)。
前五部分主要是一些理论性的基础概念,如果你不敢兴趣可以直接跳过。
- github地址: sound-processor
- 三个示例:
- demo1 ;
- demo2 ;
- demo3 ;
一、什么是声音?
声音来源于 振动 ,通过声波传播,人耳中无数 毛细胞 会将振动信号转换成电信号并通过听觉神经传递给大脑,形成人主观意识上的“声音”。声波进入人耳后,因为耳蜗的特殊构造,不同部位对声音的敏感程度是不一样的:
高频声音会被耳蜗近根部位置所感知,低频声音在近端部位置被感知,因此人对不同频率声的感受是 非线性 的,这是后续 声学计权 的基础。
二、声学计权
声学计权常见的有 频率计权 和 时间计权 ,其作用在于模拟人耳对不同频率声音的非线性感受:
1~5K Hz 15~20K Hz
人耳听觉范围如图所示:
2.1 频率计权
频率计权是作用在音频信号的频谱上的,常用的有:A、B、C、D四种:
其中 A计权 是最接近人主观感受的,它会削弱低频和高频部分中人耳不敏感的部分,所以音频可视化里要选择A计权方式,详细说明可阅读 wiki 。
2.2 时间计权
现实里声音一般是连续的,人对声音的主管感受也是声音累加的结果(想象一下,第一波声波引起耳膜振动,振动还没停止,第二波声音就来了,因此实际耳膜的振动是声波在时间上累加的结果),时间计权就是就连续时间内声音的平均值。对于变化较快的信号,我们可以使用125ms的区间来求平均,对于变化缓慢的可以采用1000ms的区间。
三、声音测量
声音测量最常用的物理量是 声压 ,描述声压的大小通常用声压级(Sound Pressure Level,SPL)。人耳可听的声压范围为2×10-5Pa~20Pa,对应的声压级范围为0~120dB。
常见声音的声压
声压常常用 分贝 来度量,这里要说明一点,分贝本身只是一种度量方式,代表测量值和参考值的对数比率:
声压级的定义:
其中 P
是测量幅值, P ref
代表人耳能听见 1000 Hz
的最小声压: 20 uP
。
四、倍频程
首先,连续的信号包含了大量的数据,我们没有必要全部处理,因此我们一般会进行采样,将连续的频率划分成一个一个区间来分析, 频程 就代表一段频率区间, 倍频程 代表频率划分的一种方案。具体来说倍频程中一段区间的上限频率与下限频率之比是常数:
具体可以看这篇文章 《什么是倍频程》
当N等于1,就是1倍频程,简称倍频程,如果N等于2,则为 1/2
倍频程。频程划分好之后,将分布于频程内的频谱求均方值得到的就是 倍频程功率谱 :
五、webaudio对音频的处理
在web端做音频可视化离不开webaudio的API,其中最重要的就是 getByteFrequencyData
( 文档 ),这个方法能获取时域信号转换之后的频域信号,详细过程如下:
- 获取原始的时域信号;
- 对其应用
Blackman window
( 布莱克曼窗函数 ),其作用是补偿DFT造成的信号畸变和能量泄漏; - 快速傅里叶变换,将时域变成频域;
- Smooth over time ,这一步是在时间维度对信号进行加权平均(webaudio只采用了2帧);
- 按照上文的声压公式转换为dB;
- 归一化,webaudio采用的归一化方式如下:
六、音频可视化中的信号处理方案
结合上述内容,我们觉得比较合理的处理方式如下:
6.1 滤波
有人会问, getByteFrequencyData
内部不是已经应用了窗函数滤波吗,为什么还要再滤波?
因为webaudio内部的窗函数主要是用于补偿信号畸变和能量泄漏,其参数都是固定的。而在音频可视化的场景下,往往视觉感受要优先于数据精确性,因此我们加了一个 高斯滤波 来滤除突刺和平滑信号,“平滑”的程度是可以通过参数任意控制的。
6.2 计权
视觉呈现应该要和人的主观听觉关联,所以计权是必要的,JavaScript的计权实现 audiojs/a-weighting 。另外我们也提供了额外的时间计权,内部会统计5个历史数据进行平均。
6.3 频程划分
我们会根据传入的上下限频率区间和置顶的输出频带数自动进行频程划分,核心代码:
// 根据起止频谱、频带数量确定倍频数: N // fu = 2^(1/N)*fl => n = 1/N = log2(fu/fl) / bandsQty let n = Math.log2(endFrequency / startFrequency) / outBandsQty; n = Math.pow(2, n); // n = 2^(1/N) const nextBand = { lowerFrequency: Math.max(startFrequency, 0), upperFrequency: 0 }; for (let i = 0; i < outBandsQty; i++) { // 频带的上频点是下频点的2^n倍 const upperFrequency = nextBand.lowerFrequency * n; nextBand.upperFrequency = Math.min(upperFrequency, endFrequency); bands.push({ lowerFrequency: nextBand.lowerFrequency, upperFrequency: nextBand.upperFrequency }); nextBand.lowerFrequency = upperFrequency; }
七、sound-processor
sound-processor 是一个极小(gzip < 3KB)的处理音频信号的库,作为音频可视化的底层部分,使用相对科学的方法处理原始音频信号并输出符合人类主观听觉的信号,内部的处理流程如下:
7.1 安装
npm install sound-processor
7.2 使用
import { SoundProcessor } from "sound-processor"; const processor = new SoundProcessor(options); // in means original signal // analyser is the AnalyserNode const in = new Uint8Array(analyser.frequencyBinCount) analyser.getByteFrequencyData(in); const out = processor.process(in);
7.3 options
-
filterParams
: 滤波参数,对象,默认undefined
,表示不滤波:-
sigma
:高斯分布的sigma参数,默认为1,表示标准正态分布,sigma越大平滑效果越明显,一般取0.1~250
之间; -
radius
:滤波半径,默认为2;
-
-
sampleRate
:采样率,可以从webaudio的context中取(audioContext.sampleRate
),一般是48000; -
fftSize
:傅里叶变换参数,默认为1024; -
startFrequency
:起始频率,默认为0; -
endFrequency
:截止频率,默认10000,配合startFrequency
可以选取任意频段的信号; -
outBandsQty
:输出频带数,对应可视化目标的数量,默认为fftSize
的一半; -
tWeight
:是否开启时间计权,默认为false
; -
aWeight
:是否开启A计权,默认为true
;
7.4 频率截取
一般音乐的频率范围在 50~10000 Hz
之间,实际中可以取的小一些,比如 100~7000 Hz
,对于不同风格以及不同乐器的声音很难取到一个统一的完美区间,另外不同的视觉风格可能也会影响频率区间。
参考材料
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Python信号处理
- Linux信号处理机制
- xenomai内核解析之信号signal(二)---xenomai信号处理机制
- Python内核阅读(二十五):信号处理机制
- 写给 PHP 程序员的信号处理教程
- 开放下载!《阿里语音与信号处理技术》精选集
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Qt 5.9 C++开发指南
王维波、栗宝鹃、侯春望 / 人民邮电出版社 / 2018-5-1 / 89.00元
本书以Qt 5.9 LTS版本为开发平台,详细介绍了Qt C++开发应用程序的技术,包括Qt应用程序的基本架构、信号与槽工作机制、图形显示的Graphics/View架构、数据编辑和显示的Model/View架构、对话框和多窗口的设计与调用方法等,介绍了常用界面组件、文件读写、绘图、图表、数据可视化、数据库、多线程、网络和多媒体等模块的使用。每个编程主题都精心设计了完整的实例程序。 通过阅读......一起来看看 《Qt 5.9 C++开发指南》 这本书的介绍吧!