单纯的音乐播放是否过于单调,在听音乐的同时如果也能看见音乐是否更加带感。本课程将带领你使用webAudio和canvas将你的音乐以你喜欢的形式可视化出来,让你的音乐动起来。
应用介绍:
利用webAudio,canvas,CSS3制作的自适应的音乐可视化应用,移动端、pc端通用
在线浏览:地址
源码下载;Github
应用核心结构介绍:
难点:
使用webAudio操作分析音频数据
使用Canvas可视化数据
音频获取及播放
构建应用前后端
Node.js搭建的后台,通过npm获取express框架,express就相当于PHP的ThingPHP,Python的Django一样的框架,然后通过npm install安装依赖包后就可以创建应用了,这里用的是ejs的模板引擎,有点类似于PHP中的<? PHPcode ?>,routes就相当于controller,views就是view,程序入口在app.js,这就是个简单的后端应用结构。
步骤:
1、安装Node.js
2、安装express应用生成器:1
2npm install -g express-generator //安装express-generator模块
express -e myApp //初始化myApp项目,并增加ejs模板引擎。 '-e':增加ejs模板引擎 (默认模板引擎是jade)
这是,会在myApp目录下生成一系列文件:views/bin/routes/public文件夹,package.json/app.js等文件。
参考:Express应用生成器
3、安装npm依赖包npm install
:将npm依赖包安装到本地文件夹里
4、安装supervisor实时监测模块npm install -g supervisor
:’-g’:表示全局安装supervisor bin/www
:监测应用。
备注:通过supervisor监测应用时,需要node.js出于启用状态
5、启动myApp应用:根据平台选择相应命令> set DEBUG=myapp & npm start
:Window平台使用命令$ DEBUG=myapp npm start
:MacOS 或 Linux平台使用命令
或者通过下面的命令来启动node.js:./bin/www
这时,在浏览器中打开 http://localhost:3000/ 网址就可以看到这个应用了。
获取服务端音频列表
routes文件夹→ index.js1
2
3
4
5
6
7
8
9
10
11
12
13
14var path = require("path");
var media = path.join(__dirname,"../public/media");
/* GET home page. */
router.get('/', function(req, res, next) {
var fs = require("fs");
fs.readdir(media,function(err,names){
if (err) {
console.log(err);
}else{
res.render('index',{title:'Passionate Music',music: names})
}
});
});
views文件夹 → index.ejs1
2
3
4
5
6<ul>
<% music.forEach(function(name){ %>
<li><%= name %></li>
<% }) %>
</ul>
ajax请求服务端音频资源数据1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23function $(s){
return document.querySelectorAll(s);
}
var lis = $("#list li");
for (var i = 0; i < lis.length; i++) {
lis[i].onclick =function(){
for (var j= 0; j < lis.length; j++) {
lis[j].className="";
}
this.className="selected";
load("/media/"+this.title);
}
}
var xhr = new XMLHttpRequest();
function load(url){
xhr.open("GET",url);
xhr.responseType = "arraybuffer";
xhr.onload = function(){
console.log(xhr.response);
}
xhr.send();
}
解码并播放音频资源
为音频解码、获取数据等操作,需要用到WebAudio.
AudioContext
AudioContext包含各个AudioNode对象以及它们的联系的对象,可以理解为audio上下文对象。绝大多数情况下,一个document中只有一个AudioContext。
创建:var ac=new window.AudioContext();
AudioContext对象属性:
destination, AudioDestinationNode对象, 所以音频的输出聚集地
currentTime, AudioContext从创建开始到当前的时间(秒)
AudioContext对象方法(函数):
decodeAudioData(被解码的buffer, 成功回调函数succ(buffer), 失败回调函数err); //异步解码
createBufferSource(); //创建AudioBufferSourceNode对象
createAnalyser(); //创建AnalyserNode对象
createGain() / createGainNode(); //创建GainNode对象
AudioBufferSourceNode
表示内存中的一段音频资源,其音频数据存在于AudioBuffer中(其buffer属性)
创建: var buffersource = ac.createBufferSource();
AudioBufferSourceNode对象属性:
buffer, AudioBuffer对象, 要播放的资源数据, 子属性:duration, 该资源时长(秒)
loop, 是否循环播放, 默认false
onended, 播放完毕事件
AudioBufferSourceNode对象方法:
start/noteOn(when=ac.currentTime, offset=0, duration=buffer.duration-offset);when:何时开始播放;offset:从音频的第几秒开始播放;duration:播放几秒
stop/noteOff(when=ac.currentTime),结束播放音频
应用中webAudio API关系图
兼容性问题解决:
window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext;
1 | var xhr = new XMLHttpRequest(); |
添加音量控制
GainNode:
改变音频音量的对象,会改变通过它的音频数据所有的sample frame的信号强度。
创建:var gainNode = ac.createGain()/ac.createGainNode();
GainNode对象属性:
gain, AudioParam对象, 通过改变其value值可以改变音频信号的强弱,, 默认的value属性值为1,通常最小值为0,最大值为1,其value值也可以大于1,小于0.1
2
3
4
5
6
7
8
9
10
11var gainNode =ac.createGain() || ac.createGainNode();
gainNode.connect(ac.destination);
function changeVolume(percent){
gainNode.gain.value = percent*percent;
}
$("#volume")[0].onchange = function(){
changeVolume(this.value/this.max);
}
$("#volume")[0].onchange();
播放bug修复
- 点击下一首歌曲时,仍会同时播放上一首歌曲。
- 点击一首歌曲(ajax尚未加载完毕),然后又点击下一首歌曲,这时会两首歌曲同时播放。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24var source =null;
var count=0;
function load(url){
var n=++count;
source && source[source.stop?"stop":"noteOff"](); //加载下一首歌时,如已存在歌曲,则停止。
xhr.abort(); //点击下一首歌时,终止上一次连接。
xhr.open("GET",url);
xhr.responseType = "arraybuffer";
xhr.onload = function(){
if (n!=count) return;
ac.decodeAudioData(xhr.response,function(buffer){
if (n!=count) return;
var bufferSource = ac.createBufferSource();
bufferSource.buffer=buffer;
bufferSource.connect(gainNode);
bufferSource[bufferSource.start?"start":"noteOn"](0);
source=bufferSource;
},function(err){
console.log(err);
});
}
xhr.send();
}
音频可视化
分析音频资源
AnalyserNode:
音频分析对象,它能实时的分析音频资源的频域和时域信息,但不会对音频流做任何处理。
创建: var analyser = ac.createAnalyser();
AnalyserNode对象属性和方法:
fftSize, 设置FFT(FFT是离散傅立叶变换的快速算法,用于将一个信号变换到频域)值的大小,用于分析得到频域 为32-2048之间2的整数次方, 默认为2048, 实时得到的音频频域的数据个数为fftSize的一半。这里相当于分析的精度
frequencyBinCount, 实时得到的频域数据, 为fftSize的一半
getByteFrequencyData(Uint8Array); //复制当前频域数据到Uint8Array(8bit unsigend int array,8位无符号整形类型化数组)中
1 | var analyser = ac.createAnalyser(gainNode); |
利用Canvas将音乐数据可视化
柱状图
1 | var box=$("#box")[0]; |
圆点图
1 | var Dots=[]; |
应用优化
webAudio API梳理
webAudio核心功能封装为对象
1 | function MusicVisualizer(obj){ |
柱状图美化/圆点图美化
主要是修改draw、getDots函数中颜色、宽、高等数据。
参考资源:
- 使用Express框架应用生成器快速搭建一个应用骨架 http://blog.csdn.net/kongjunchao159/article/details/51121482
- WEB AUDIO API简易入门教程 http://newhtml.net/web-audio-api%E7%AE%80%E6%98%93%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B/
- 通过Web Audio API可视化输出MP3音乐频率波形 http://ourjs.com/detail/54d48406232227083e000029
- Web Audio介绍 http://www.cnblogs.com/jimmychange/p/3498911.html
- 源码下载;Github