声明: 原创文章,未经允许不得转载。

音频可视化是一个“听”起来非常“美”好的话题,其复杂程度很大程度上依赖视觉方案(一些例子),不同的视觉方案决定了你的技术方案选型,比如three.js,pixi.js等引擎。

不管你选用什么渲染方案,处理音频信号部分是相通的,本文会围绕音频信号的处理进行阐述,期望能够给大家普及一下音频相关的基础知识(由于能力所限难免疏错,欢迎指出)。

前五部分主要是一些理论性的基础概念,如果你不敢兴趣可以直接跳过。

三个示例(音频放在git上加载较慢,需要等久一点):

一、什么是声音?

声音来源于 振动,通过声波传播,人耳中无数 毛细胞 会将振动信号转换成电信号并通过听觉神经传递给大脑,形成人主观意识上的“声音”。声波进入人耳后,因为耳蜗的特殊构造,不同部位对声音的敏感程度是不一样的:

高频声音会被耳蜗近根部位置所感知,低频声音在近端部位置被感知,因此人对不同频率声的感受是非线性的,这是后续声学计权的基础。

二、声学计权

声学计权常见的有频率计权和时间计权,其作用在于模拟人耳对不同频率声音的非线性感受:

对低频部分声音不敏感;

最灵敏的区域在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,对于不同风格以及不同乐器的声音很难取到一个统一的完美区间,另外不同的视觉风格可能也会影响频率区间。

参考材料

傅里叶变换音频可视化_音频可视化中的信号处理方案相关推荐

  1. python音频 降噪_从视频中提取音频数据,然后应用傅里叶对音频降噪(python)...

    视频准备 QQ有热键 然后随便打开一个视频网站进行录屏 我选择B站 从视频中提取音频 需要安装包moviepy pip install moviepy 提取代码 from moviepy.editor ...

  2. python音频特征提取_音频特征提取——librosa工具包使用

    作者:桂. 时间:2017-05-06  11:20:47 前言 本文主要记录librosa工具包的使用,librosa在音频.乐音信号的分析中经常用到,是python的一个工具包,这里主要记录它的相 ...

  3. 数据可视化 信息可视化_动机可视化

    数据可视化 信息可视化 John Snow's map of Cholera cases near London's Broad Street. 约翰·斯诺(John Snow)在伦敦宽街附近的霍乱病 ...

  4. 数据图表可视化_数据可视化如何选择正确的图表第1部分

    数据图表可视化 According to the World Economic Forum, the world produces 2.5 quintillion bytes of data ever ...

  5. 音频剪切_音频编辑入门指南:剪切,修剪和排列

    音频剪切 Audacity novices often start with lofty project ideas, but sometimes they lack the basics. Know ...

  6. celery 可视化_在Flask中使用Celery进行多任务分布执行

    关键字:Flask, Redis, RabbitMQ, Celery, Broker, Backend 前言 在后端服务器有时候需要处理耗时较长的任务,例如发送电子邮件,在处理这些任务时,这个线程就处 ...

  7. 注意力机制可视化_目标跟踪中的(STAM)时空注意力机制

    目标跟踪分为单目标跟踪和多目标跟踪,单目标跟踪较为简单,这里我们只讨论多目标跟踪. 多目标跟踪的遮挡问题 多目标跟踪时特别容易发生目标间的相互遮挡,从而导致严重的预测偏移问题,如下图所示: 红色框的行 ...

  8. java audioinputstream 读取音频文件_从原始文件中获取最多x个字节的AudioInputStream(剪切音频文件)...

    小编典典 下面的代码向您展示如何复制音频流的一部分,从一个文件读取并写入另一个文件. import java.io.*; import javax.sound.sampled.*; class Aud ...

  9. 机器学习 可视化_机器学习-可视化

    机器学习 可视化 机器学习导论 (Introduction to machine learning) In the traditional hard-coded approach, we progra ...

最新文章

  1. 宇宙和你,本质上其实只是个八维数字?
  2. RemoteApp连接时所需要的证书
  3. vshpere esxi6.7安装
  4. 为什么判断 n 是否为质数只需除到开平方根就行了?(直接证明)
  5. 计算机网络TCPP是一组什么,WWW的全称是什么?WWW中文名称是啥?
  6. 西门子PLC S7-1200安装指南
  7. 考试倒计时,计算机二级重难点汇总【39套历年考题】
  8. 机器学习数据不平衡问题及其解决方法
  9. 标准HTML代码框架解析
  10. 自由软件之父Richard Stallman及其思想
  11. Jquery UI 教程
  12. Golang实战【IP池-自动切换IP爬虫】
  13. 白盒测试 | 用例设计方法之条件组合覆盖
  14. 华为2019 秋招笔试题
  15. excel查标准正态分布_利用Excel的NORMSDIST计算正态分布函数表1
  16. ipad上编译运行代码_是否可以在iPad上编写和运行PHP代码?
  17. 彻底删除的视频怎么恢复?找回丢失的视频有3种方式
  18. Linux问题:Cannot prepare internal mirrorlist: No URLs in mirrorlist
  19. 经典网页设计:25个应用视差滚动的单页网站
  20. 【详细图文】Ubuntu 16.04更改下载源 解决软件包下载慢问题

热门文章

  1. java hbase 批量查询数据_java Hbase 批量读取
  2. matlab 柱状图不同颜色(取巧哈)
  3. Linux多线程学习 - sched_yield() CPU让权
  4. 输出菱形(C语言,萌新向)
  5. Java设计模式学习以及底层源码分析
  6. python+twilio实现打电话和发短信功能
  7. win10电脑插入耳机一边声音大一边声音小
  8. sql 获取当前年份的12个月
  9. python 字符串方法 replace_python字符串方法replace()简介
  10. 阿里云增强版实人认证--银行卡要素核验