文档章节

AudioContext技术和音乐可视化(1)

御坂网络路由器
 御坂网络路由器
发布于 2018/11/07 02:48
字数 1506
阅读 157
收藏 2

写在最前,测试博客在这里,直接欣赏完成可视化效果。代码不日在github公开,性能目前巨烂,RadialGradient损耗巨大,优化正在提上日程。

转载注明来源。

扒掉网页上js的烦请留下js里的顶端注释谢谢。。虽然我代码是写的挺烂的。如果转发到别的地方了能注明一下作者和来源的话我会很开心的。

https://th-zxj.club 这是你从未体验过的船新版本

Intro

因为自己搭了个博客,一时兴起,就想写个动态的博客背景。毕竟用django后端渲染,前端只有jquery和bootstrap已经够low了,虽说极简风格也很棒,但是多少有点亮眼的东西才好和别人吹牛不是吗。

为了方便讲解,整个思路分为两个部分:音乐播放和背景绘制。

一、音乐播放

1.1 AudioContext

概述部分懒得自己写,参考MDN的描述。

AudioContext接口表示由音频模块连接而成的音频处理图,每个模块对应一个AudioNodeAudioContext可以控制它所包含的节点的创建,以及音频处理、解码操作的执行。做任何事情之前都要先创建AudioContext对象,因为一切都发生在这个环境之中。

1.2 浏览器支持状况

AudioContext标准目前还是草案,不过新chrome已经实现了。我使用的chrome版本如下。

版本 70.0.3538.77(正式版本) (64 位)

如果发现console报错或者其他问题请检查浏览器版本,所有支持的浏览器可以在这个链接查看。

1.3 AudioContext和音频处理图

关于AudioContext我的了解不是很深入,所以只在需要用到的部分进行概述。

首先,关于音频处理图的概念。

这个名词不甚直观,我用过虚幻,所以用虚幻的Blueprint来类比理解。音频处理图,其实是一系列音频处理的模块,连接构成一张数据结构中的“图”,从一般使用的角度来讲,一个播放音频的图,就是AudioSource -> AudioContext.destination,两个节点构成的图。其中有很多特殊的节点可以对音频进行处理,比如音频增益节点GainNode

对于音频处理的部分介绍就到这里为止,毕竟真的了解不多,不过从MDN的文档看,可用的处理节点还是非常多的,就等标准制订完成了。

1.4 加载音频文件并播放

音频文件加载使用典型的JavaScript接口FileReader实现。

一个非常简单的实例是这样

首先是html里写上input

<html>
    <body>
        <input type="file" accept="audio/*" onchange="onInputChange">
    </body>
</html>

然后在javascript里读文件内容。

function onInputChange(files){
    const reader = new FileReader();
	reader.onload = (event) => {
   		// event.target.result 就是我们的文件内容了
	}
	reader.readAsArrayBuffer(files[0])
}

文件读取就是这么简单,所以回到那个问题:说了那么多,音乐到底怎么放?

答案是用AudioContextdecodeAudioData方法。

所以从上面的js里做少许修改——

// 创建一个新的 AudioContext
const ctx = new AudioContext();

function onInputChange(files){
    const reader = new FileReader();
	reader.onload = (event) => {
   		// event.target.result 就是我们的文件内容了
        // 解码它
        ctx.decodeAudioData(event.target.result).then(decoded => {
            // 解码后的音频数据作为音频源
            const audioBufferSourceNode = ctx.createBufferSource();
            audioBufferSourceNode.buffer = decoded;
            // 把音源 node 和输出 node 连接,boom——
            audioBufferSourceNode.connect(ctx.destination);
            audioBufferSourceNode.start(0);
            // 收工。
        });
	}
	reader.readAsArrayBuffer(files[0])
}

1.5 分析频谱

频谱的概念我建议搜一下傅里叶变换,关于时域和频域转换的计算过程和数学原理直接略(因为不懂),至今我还只理解到时域和频域的概念以及傅里叶变换的实现接受采样返回采样数一半长的频域数据......

不班门弄斧了。

以前写python的时候用的numpy来进行傅里叶变换取得频域数据,现在在浏览器上用js着实有些难受。不过幸好,AudioContext直接支持了一个音频分析的node,叫做AudioAnalyserNode

这个Node处于音源Node和播放输出Node之间,想象一道数据流,音源Node把离散的采样数据交给Analyser,Analyser再交给输出Node。

直接看代码实例。

// 创建一个新的 AudioContext
const ctx = new AudioContext();
// 解码后的音频数据作为音频源
// 为了方便管理,将这些Node都放置在回调函数外部
const audioBufferSourceNode = ctx.createBufferSource();

// 创建音频分析Node!
const audioAnalyser = ctx.createAnalyser();
// 注意注意!这里配置傅里叶变换使用的采样窗口大小!比如说,我们要256个频域数据,那么采样就应该是512。
// 具体对应频率请自行搜傅里叶变换相关博文。
audioAnalyser.fftSize = 512;

function onInputChange(files){
    const reader = new FileReader();
	reader.onload = (event) => {
   		// event.target.result 就是我们的文件内容了
        // 解码它
        ctx.decodeAudioData(event.target.result).then(decoded => {
            // 停止原先的音频源
            audioBufferSourceNode.stop();
            // 先把音频源Node和Analyser连接。
            audioBufferSourceNode.connect(audioAnalyser);
            // 然后把Analyser和destination连接。
            audioAnalyser.connect(ctx.destination);
            // 修改音频源数据
            audioBufferSourceNode.buffer = decoded;
            audioBufferSourceNode.start(0);
            // 收工。
        });
	}
	reader.readAsArrayBuffer(files[0])
}

window.requestAnimationFrame(function() {
    // 读取频域数据
    const freqData = new Uint8Array(audioAnalyser.frequencyBinCount);
    console.log(freqData);
})

频域数据是二维的,频率(数组下标)和能量(下标对应值)。悄悄补一句,数学上应该说是该频率函数图像的振幅?

其实获得了这个频域数据,继续画出我们常见的条状频域图就很容易了。参考我一朋友的博客。misuzu.moe,可以看看效果。

关于AudioContext的介绍先到此为止,等我找时间继续写。

PS:代码不保证复制粘贴就能运行,领会精神,遇到问题查查文档。MDN比我这博客详细多了。

© 著作权归作者所有

共有 人打赏支持
御坂网络路由器
粉丝 1
博文 22
码字总数 34661
作品 0
广州
程序员
私信 提问
HTML5 可视化音乐播放器--HTML5VisualizationPlayer

最近想做一个音乐电台,就做了一款 HTML5 音乐播放器,我把它分享出来,技术需要分享才能得到进步嘛! 该播放器可以根据音乐绘制频谱,所以我叫它可视化音乐播放器,播放器支持谷歌浏览器和火...

PoppinRubo
2017/05/02
572
0
AudioContext技术和音乐可视化(2)

Intro 转载请注明来源,可以在测试博客查看完成效果。 本篇讲述如何绘制动态的星空,其实关联到频域数据已经没什么悬念了。 一、使用Canvas绘图 1.1 位置和大小 绘制背景的第一要务便是把can...

御坂网络路由器
2018/11/08
0
0
Chrome 66禁止声音自动播放之后

声音无法自动播放这个在IOS/Android上面一直是个惯例,桌面版的Safari在2017年的11版本也宣布禁掉带有声音的多媒体自动播放功能,紧接着在2018年4月份发布的Chrome 66也正式关掉了声音自动播...

人人网FED
2018/05/13
0
0
Chrome 66 禁止声音自动播放,开发怎么应对?

声音无法自动播放这个在IOS/Android上面一直是个惯例,桌面版的Safari在2017年的11版本也宣布禁掉带有声音的多媒体自动播放功能,紧接着在2018年4月份发布的Chrome 66也正式关掉了声音自动播...

h4cd
2018/05/13
9.6K
11
html5的audio和audioContext尝试

audio和audioContext支持的文件格式有限,如果要使用的话,尽量用mp3格式,我在这里用的是wma格式的,不管是audio表情还是用audioContext,都不能播放。可能还有其他的解决办法,等以后用的时...

boogoogle
2016/03/11
63
0

没有更多内容

加载失败,请刷新页面

加载更多

告别2018

今天中午从喵喵家回来之后,倒头就睡到下午4点了。可能是之前透支的身体,在我放松下来后,开始觉得疲惫了,所以最近估计会进入嗜睡期。醒来之后,拿了包花生,开了瓶低糖菊花茶,听着网易云...

七木网络科技
30分钟前
1
0
MySql数据库分表分区实践

1. 背景 —— 公司物联网项目 海量设备通过物联网服务接入云端,设备每30s上报一次自身数据(以下称为动态数据)。 物联网服务将设备上报的数据转发给数据处理网关,由数据入库网关执行批量入...

吴伟祥
43分钟前
2
0
大表关联走hash优化

大表关联走hash? 案例: ---- 反正我执行过1个多小时,没有跑完 SELECT a.id AS order_id ,b.s_id AS bill_id, d.id AS sub_order_id, d.deal_oper_id FROM EM_ORDER PARTITION(EM_ORDER_20......

hnairdb
55分钟前
1
0
MySQL查询执行

当我们希望MySQL能够以更高的性能运行查询时,最好的办法就是弄清楚MySQL是如何优化和执行查询的。一旦理解了这一点,很多查询优化工作实际上就是遵循一些原则让优化器能够按照预想的合理方式...

问题终结者
今天
1
0
CDH5动静态资源池配置与回滚

关于动态 静态资源池的配置以前都有提过,可以从以下几篇了解: YARN动态资源池配置案例 https://yq.aliyun.com/ziliao/346856# Hadoop YARN配置参数剖析(4)—Fair Scheduler相关参数 Hadoop...

hblt-j
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部