使用HTML5 API(AudioContext)实现可视化频谱效果

使用HTML5 API(AudioContext)实现可视化频谱效果,第1张

概述HTML5 可视化频谱效果如今的HTML5技术正让网页变得越来越强大,通过其Canvas标签与AudioContext对象可以轻松实现之前在Flash或Native App中才能实现的频谱指示器的功能。Demo: Cyandev Works - HTML5 Audio Visualizing开始使用 HTML5 可视化频谱效果

如今的HTML5技术正让网页变得愈来愈强大,通过其Canvas标签与AudioContext对象可以轻松实现之前在Flash或Native App中才能实现的频谱唆使器的功能。

Demo: Cyandev Works - HTML5 Audio Visualizing

开始使用AudioContext@H_403_12@

The AudioContext interface represents an audio-processing graph built from audio modules linked together,each represented by an AudioNode.

根据MDN的文档,AudioContext是1个专门用于音频处理的接口,并且工作原理是将AudioContext创建出来的各种节点(AudioNode)相互连接,音频数据流经这些节点并作出相应处理。

创建AudioContext对象

由于阅读器兼容性问题,我们需要为不同阅读器配置AudioContext,在这里我们可以用下面这个表达式来统1对AudioContext的访问。

var AudioContext = window.AudioContext || window.webkitaudiocontext;var audioContext = new AudioContext(); //实例化AudioContext对象

附. 阅读器兼容性

阅读器 Chrome firefox IE Opera Safari
支持版本 10.0 25.0 不支持 15.0 6.0

固然,如果阅读器不支持的话,我们也没有办法,用IE的人们我想也不需要这些效果。但最好实践是使用的时候判断1下上面声明的变量是不是为空,然后再做其他 *** 作。

解码音频文件

读取到的音频文件是2进制类型,我们需要让AudioContext先对其解码,然后再进行后续 *** 作。

audioContext.decodeAudioData(binary,function(buffer) { ... });

方法decodeAudioData被调用后,阅读器将开始解码音频文件,这需要1定时间,我们应当让用户知道阅读器正在解码,解码成功后会调用传进去的回调函数,decodeAudioData还有第3个可选参数是在解码失败时调用的,我们这里就先不实现了。

创建音频处理节点

这是最关键的1步,我们需要两个音频节点:

AudioBufferSourceNodeAnalyserNode

前者是用于播放解码出来的buffer的节点,而后者是用于分析音频频谱的节点,两个节点顺次连接就可以完成我们的工作。

创建AudioBufferSourceNodevar audioBufferSourceNode;audioBufferSourceNode = audioContext.createBufferSource();创建AnalyserNodevar analyser;analyser = audioContext.createAnalyser();analyser.fftSize = 256;

上面的fftSize是用于肯定FFT大小的属性,那FFT是甚么高3的博主还不知道,其实也不需要知道,总之最后获得到的数组长度应当是fftSize值的1半,还应当保证它是以2为底的幂。

连接节点audioBufferSourceNode.connect(analyser);analyser.connect(audioContext.destination);

上面的audioContext.destination是音频要终究输出的目标,我们可以把它理解为声卡。所以所有节点中的最后1个节点应当再连接到audioContext.destination才能听到声音。

播放音频

所有工作就绪,在解码终了时调用的回调函数中我们就能够开始播放了。

audioBufferSourceNode.buffer = buffer; //回调函数传入的参数audioBufferSourceNode.start(0); //部份阅读器是noteOn()函数,用法相同

参数代表播放出发点,我们这里设置为0意味着从头播放。

文件读取@H_403_12@

HTML5支持文件选择、读取的特性,我们利用这个特性可以实现不上传,即播放的功能。


HTML标签

在你的页面中找个位置插入:

<input ID="fileChooser" type="file" />Js逻辑var file;var fileChooser = document.getElementByID('fileChooser');fileChooser.onchange = function() { if (fileChooser.files[0]) { file = fileChooser.files[0]; // Do something with 'file'... }}使用fileReader异步读取文件var fileContent;var fileReader = new fileReader();fileReader.onload = function(e) { fileContent = e.target.result; // Do something with 'fileContent'...}fileReader.readAsArrayBuffer(file);

其实这里的fileContent就是上面AudioContext要解码的那个binary,至此两部份的工作就能够连起来了。

WARNING:

Chrome或firefox阅读器的跨域访问限制会使fileReader在本地失效,Chrome用户可在调试时添加命令行参数:

Chrome.exe --disable-web-security
Canvas绘制频谱@H_403_12@

这1部份我不打算详细叙述,就提几个重点。

AnalyserNode数据解析

在绘制之前通过下面的方法获得到AnalyserNode分析的数据:

var dataArray = new Uint8Array(analyser.frequencyBinCount);analyser.getByteFrequencyData(dataArray);

数组中每一个元素是从0到fftSize属性值的数值,这样我们通过1定比例就可以控制能量条的高度等状态。

requestAnimationFrame的使用

要使动画动起来,我们需要不断重绘Canvas标签里的内容,这就需要requestAnimationFrame这个函数了,它可以帮你以60fps的帧率绘制动画。

使用方法:

var draw = function() { // ... window.requestAnimationFrame(draw);}window.requestAnimationFrame(draw);

这段代码应当不难理解,就是1个类似递归的调用,但不是递归,有点像AndroID中的postInvalIDate

实例代码

贴上我写的1段绘制代码:

var render = function() { ctx = canvas.getContext("2d"); ctx.strokeStyle = "#00d0ff"; ctx.linewidth = 2; ctx.clearRect(0,0,canvas.wIDth,canvas.height); //清算画布 var dataArray = new Uint8Array(analyser.frequencyBinCount); analyser.getByteFrequencyData(dataArray); var step = Math.round(dataArray.length / 60); //采样步长 for (var i = 0; i < 40; i++) { var energy = (dataArray[step * i] / 256.0) * 50; for (var j = 0; j < energy; j++) { ctx.beginPath(); ctx.moveto(20 * i + 2,200 + 4 * j); ctx.lineto(20 * (i + 1) - 2,200 + 4 * j); ctx.stroke(); ctx.beginPath(); ctx.moveto(20 * i + 2,200 - 4 * j); ctx.lineto(20 * (i + 1) - 2,200 - 4 * j); ctx.stroke(); } ctx.beginPath(); ctx.moveto(20 * i + 2,200); ctx.lineto(20 * (i + 1) - 2,200); ctx.stroke(); } window.requestAnimationFrame(render);}

OK,大致就是这样,以后可以加1些CSS样式,完善1下业务逻辑,这里就不再阐释了。最后贴上整理好的全部代码:

HTML 部份<HTML> <head> <Title>HTML5 Audio Visualizing</Title> <style type="text/CSS"> body { background-color: #222222 } input { color: #ffffff } #wrapper { display: table; wIDth: 100%; height: 100%; } #wrapper-inner { display: table-cell; vertical-align: mIDdle; padding-left: 25%; padding-right: 25%; } #tip { color: #fff; opacity: 0; Transition: opacity 1s; -moz-Transition: opacity 1s; -webkit-Transition: opacity 1s; -o-Transition: opacity 1s; } #tip.show { opacity: 1 } </style> <script type="text/JavaScript" src="./index.Js"></script> </head> <body> <div ID="wrapper"> <div ID="wrapper-inner"> <p ID="tip">DeCoding...</p> <input ID="fileChooser" type="file" /> <br> <canvas ID="visualizer" wIDth="800" height="400">Your browser does not support Canvas tag.</canvas> </div> </div> </body></HTML>Js部份var AudioContext = window.AudioContext || window.webkitaudiocontext; //Cross browser variant.var canvas,ctx;var audioContext;var file;var fileContent;var audioBufferSourceNode;var analyser;var loadfile = function() { var fileReader = new fileReader(); fileReader.onload = function(e) { fileContent = e.target.result; decodecfile(); } fileReader.readAsArrayBuffer(file);}var decodecfile = function() { audioContext.decodeAudioData(fileContent,function(buffer) { start(buffer); });}var start = function(buffer) { if(audioBufferSourceNode) { audioBufferSourceNode.stop(); } audioBufferSourceNode = audioContext.createBufferSource(); audioBufferSourceNode.connect(analyser); analyser.connect(audioContext.destination); audioBufferSourceNode.buffer = buffer; audioBufferSourceNode.start(0); showTip(false); window.requestAnimationFrame(render); //先判断是不是已调用1次}var showTip = function(show) { var tip = document.getElementByID('tip'); if (show) { tip.classname = "show"; } else { tip.classname = ""; }}var render = function() { ctx = canvas.getContext("2d"); ctx.strokeStyle = "#00d0ff"; ctx.linewidth = 2; ctx.clearRect(0,canvas.height); var dataArray = new Uint8Array(analyser.frequencyBinCount); analyser.getByteFrequencyData(dataArray); var step = Math.round(dataArray.length / 60); for (var i = 0; i < 40; i++) { var energy = (dataArray[step * i] / 256.0) * 50; for (var j = 0; j < energy; j++) { ctx.beginPath(); ctx.moveto(20 * i + 2,200); ctx.stroke(); } window.requestAnimationFrame(render);}window.onload = function() { audioContext = new AudioContext(); analyser = audioContext.createAnalyser(); analyser.fftSize = 256; var fileChooser = document.getElementByID('fileChooser'); fileChooser.onchange = function() { if (fileChooser.files[0]) { file = fileChooser.files[0]; showTip(true); loadfile(); } } canvas = document.getElementByID('visualizer');}

以上。

总结

以上是内存溢出为你收集整理的使用HTML5 API(AudioContext)实现可视化频谱效果全部内容,希望文章能够帮你解决使用HTML5 API(AudioContext)实现可视化频谱效果所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1016992.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-23
下一篇 2022-05-23

发表评论

登录后才能评论

评论列表(0条)

保存