手把手教你用Js实现音频可视化

HTML5中提供了Web Audio API,开发者可以通过这个API为音频添加特效,实现音频可视化效果。下面我们就来一步步实现一个音频可视化webapp,文中描述如有错误或不足,欢迎斧正。
项目github地址,欢迎star,哈哈~

创建AudioContext

var audioCtx = new (window.AudioContext || window.webkitAudioContext)();

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

创建AudioBufferSourceNode

var AudioBufferSourceNode = audioCtx.createBufferSource();

AudioBufferSourceNode接口可以通过AudioBuffer对象来播放音频数据。下面我们需要获得音频数据,转换成AudioBuffer对象,赋值到AudioBufferSourceNode的buffer属性。

获取音频数据

这边所获得的音频数据最终是要转换成AudioBuffer对象,供AudioBufferSourceNode使用。AudioBuffer对象可以通过AudioContext.createBuffer来创建或者通过AudioContext.decodeAudioData解码音轨后返回。这边,我们decodeAudioData()方法解码来获得。decodeAudioData()方法可用于异步解码音频文件中的ArrayBuffer。ArrayBuffer数据可以通过XMLHttpRequest或者FileReader来获取。

FileReader获取本地音频ArrayBuffer

页面中添加input标签来获取本地音频

<input id="loadfile" type="file">

FileReader获取ArrayBuffer类型音频数据

document.getElementById('loadfile').onchange = function(){
    var file = this.files[0];
    var fr = new FileReader();

    fr.onload = function(e){
        audioCtx.decodeAudioData(e.target.result,function(buffer){
            playFun(buffer);  // 解码后返回的AudioBuffer对象作为播放函数的参数传入
        },function(err){
            console.log(err);
        })
    }
    fr.readAsArrayBuffer(file);
}
Ajax获取音频数据

这边把ajax获取音频数据封装到一个函数中

function getData() {
  var request = new XMLHttpRequest();
  request.open('GET', url, true);
  request.responseType = 'arraybuffer'; // 设置数据类型为arraybuffer
  request.onload = function() {
    var audioData = request.response;
    audioCtx.decodeAudioData(audioData, function(buffer) {
        playFun(buffer); 
      },
      function(e){"Error with decoding audio data" + e.err});
  }
  request.send();
}

播放音频数据

现在我们已经获得音频数据并将其转换成AudioBuffer对象,下面就是音频数据的播放

function playFun(buffer){
  AudioBufferSourceNode.buffer = buffer; // AudioBuffer数据赋值给buffer属性
  //AudioBufferSourceNode.connect(audioCtx.destination); // 如果只是播放音频,这边就直接将AudioBufferSourceNode连接到AudioDestinationNode
  AudioBufferSourceNode.connect(AnalyserNode);  // 实现播放后,需要将bufferSourceNode连接到AnalyserNode,才能通过AnalyserNode获取后面可视化所需的数据
  AudioBufferSourceNode.loop = true;  // 循环播放,默认为false
  AudioBufferSourceNode.start(0); // 开始播放音频
}

音频数据可视化

创建AnalyserNode
var AnalyserNode = audioCtx.createAnalyser();

AnalyserNode节点可以提供实时的频率及时间域分析的信息。

获取音频频域数据
var arr = new Uint8Array(AnalyserNode.frequencyBinCount);//用于存放音频数据的数组,其长度是fftsize的一半
requestAnimationFrame = window.requestAnimationFrame ||
            window.webkitrequestAnimationFrame ||
            window.mozrequestAnimationFrame;//兼容
function fn(){
  AnalyserNode.getByteFrequencyData(arr);// 将音频频域数据复制到传入的Uint8Array数组
  draw(arr); // 频域数据作为参数传入绘制函数draw
  requestAnimationFrame(fn);
}
requestAnimationFrame(fn);

AnalyserNode.getByteTimeDomainData()方法用于获取音频时域数据,AnalyserNode.getByteFrequencyData()方法用于获取音频频域数据。当获取频域数据时,我们需要通过设置AnalyserNode.fftSize来控制频域数据转换长度;fftSize越大,其频域转换计算时间越长,其默认值为2048。同时,AnalyserNode.frequenceBinCount属性值与fftSize相关,其为fftSize值的一半,其决定音频可视化时有多少数值点。

音频音量控制

创建GainNode
GainNode = Musicvisualizer.ac[audioCtx.createGain?"createGain":"createGainNode"]();
AnalyserNode.connect(GainNode);  // AnalyserNode连接到GainNode
GainNode.connect(audioCtx.destination);  // GainNode连接到AudioDestinationNode

GainNode 接口表示音量变更,我们一般把这个节点放到倒数第二个进行连接,最后再将GainNode连接到AudioDestinationNode
至此,依赖Web Audio API实现音频可视化的整个过程就完成了。下面这幅图展示了整个流程。

Web Audio API音频可视化示例流程图

效果展示

最后,通过绘制,我们实现的效果图如下。数据实现了柱状和点状的可视化效果(项目github地址)。

MusicVisualizer.gif

参考

Web Audio API
Web Audio API的运用
基于Web Audio API实现音频可视化效果

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容