Web Audi怎么绘制音频图谱
导读:本文共2599.5字符,通常情况下阅读需要9分钟。同时您也可以点击右侧朗读,来听本文内容。按键盘←(左) →(右) 方向键可以翻页。
摘要: 实现思路先介绍下小编的整体思路吧。所谓的音频图谱,其实只是将声音的响度具象化为一个波形图,响度高对应的波形高,响度低波形也就低。所以第一步,我们可以通过xhr拿到一个音频文件的数据。那么,第二步便是如何处理这组数据,让数据能够比较真实的反应音频的响度。这时候就需要前端的Web Audio Api来发挥作用了,具体如何处理,我们后面详细说明。完成数据处理之后,最后... ...
目录
(为您整理了一些要点),点击可以直达。实现思路
先介绍下小编的整体思路吧。所谓的音频图谱,其实只是将声音的响度具象化为一个波形图,响度高对应的波形高,响度低波形也就低。所以第一步,我们可以通过xhr拿到一个音频文件的数据。那么,第二步便是如何处理这组数据,让数据能够比较真实的反应音频的响度。这时候就需要前端的Web Audio Api来发挥作用了,具体如何处理,我们后面详细说明。完成数据处理之后,最后一步就是需要根据数据绘制出波形图,这里我们使用canvas来做波形图的绘制。
获取音频文件
首先,我们利用fetch,来获取一个线上音频。这里,我们借用一下wavesuffer官网demo中用的线上音频来做示范。
//音频urlletaudioUrl='https://wavesurfer-js.org/example/media/demo.wav';//创建音频上下文letaudioCtx=new(window.AudioContext||window.webkitAudioContext)();//创建音频源letsource=audioCtx.createBufferSource();/**通过fetch下载音频,responseType设置为'arrayBuffer',我们以arrayBuffer格式接收返回的数据*/fetch(audioUrl,{method:'GET',responseType:'arraybuffer',}).then(res=>{returnres.arrayBuffer();}).then(data=>{//处理音频数据initAudio(data);});
利用Web Audio Api 处理音频数据
拿到音频数据之后,我们需要利用Web Audio Api,来处理音频数据,实现音频的播放,暂停等操作以及我们后续的波形图绘制。这里简单介绍下,Web Audio Api是一组非常强大的Api,它提供了在Web中控制音频、处理音频的一整套有效通用的系统。它能够允许开发着,控制音频,自选音频源、对音频添加特效,使音频可视化,添加空间效果,添加混响等等。而我们今天要实现的功能,仅仅只用到了其中几个Api,整体流程如下:
//audio初始化functioninitAudio(data){//音频数据解码//decodeAudioData方法接收一个arrayBuffer数据作为参数,这也是为什么前面fetch音频时设置以arrayBuffer格式接收数据audioCtx.decodeAudioData(data).then(buffer=>{//decodeAudioData解码完成后,返回一个AudioBuffer对象//绘制音频波形图drawWave(buffer);//连接音频源source.buffer=buffer;source.connect(audioCtx.destination);//音频数据处理完毕alert('音频数据处理完毕!');});}//webaudio规范不允许音频自动播放,需要用户触发页面事件来触发播放,这里我们增加一个播放按钮,数据处理完毕后点击播放document.querySelector('#btn').onclick=()=>{//播放音频source.start(0);}
通过解码后的音频数据,绘制波形图
音频数据通过AudioContext解码后,返回一个AudioBuffer对象,这个对象,保存有音频的采样率、声道、pcm数据等信息。通过getChannelData方法可以获取到音频某个声道的pcm数据。返回的是一个Float32Array对象,数值范围在-1到1之间。音频数据比较庞大,每一秒钟可能包含成千上万的数据,因此我们在做图形绘制时,需要对数据进一步采样。比如,这里我们采用每1000条数据中,取一个最大值(正数)一个最小值(负数)来绘制图形;
//绘制波形图functiondrawWave(buffer){//buffer.numberOfChannels返回音频的通道数量,1即为单声道,2代表双声道。这里我们只取一条通道的数据letdata=[];letoriginData=buffer.getChannelData(0);//存储所有的正数据letpositives=[];//存储所有的负数据letnegatives=[];//先每隔100条数据取1条for(leti=0;i<originData.length;i+=100){data.push(originData[i]);}//再从data中每10条取一个最大值一个最小值for(letj=0,len=parseInt(data.length/10);j<len;j++){lettemp=data.slice(j*10,(j+1)*10);positives.push(Math.max.apply(null,temp));negatives.push(Math.min.apply(null,temp));}//创建canvas上下文letcanvas=document.querySelector('#canvas');if(canvas.getContext){letctx=canvas.getContext('2d');canvas.width=positives.length;letx=0;lety=100;letoffset=0;ctx.fillStyle='#fa541c';ctx.beginPath();ctx.moveTo(x,y);//canvas高度200,横坐标在canvas中点100px的位置,横坐标上方绘制正数据,下方绘制负数据//先从左往右绘制正数据//x+0.5是为了解决canvas1像素线条模糊的问题for(letk=0;k<positives.length;k++){ctx.lineTo(x+k+0.5,y-(100*positives[k]));}//再从右往左绘制负数据for(letl=negatives.length-1;l>=0;l--){ctx.lineTo(x+l+0.5,y+(100*Math.abs(negatives[l])));}//填充图形ctx.fill();}};
</div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
Web Audi怎么绘制音频图谱的详细内容,希望对您有所帮助,信息来源于网络。