本文小编为大家详细介绍“Web Audi怎么绘制音频图谱”,内容详细,步骤清晰,细节处理妥当,希望这篇“Web Audi怎么绘制音频图谱”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。
先介绍下小编的整体思路吧。所谓的音频图谱,其实只是将声音的响度具象化为一个波形图,响度高对应的波形高,响度低波形也就低。所以第一步,我们可以通过xhr拿到一个音频文件的数据。那么,第二步便是如何处理这组数据,让数据能够比较真实的反应音频的响度。这时候就需要前端的Web Audio Api来发挥作用了,具体如何处理,我们后面详细说明。完成数据处理之后,最后一步就是需要根据数据绘制出波形图,这里我们使用canvas来做波形图的绘制。
首先,我们利用fetch,来获取一个线上音频。这里,我们借用一下wavesuffer官网demo中用的线上音频来做示范。
// 音频url let audioUrl = 'https://wavesurfer-js.org/example/media/demo.wav'; // 创建音频上下文 let audioCtx = new (window.AudioContext || window.webkitAudioContext)(); // 创建音频源 let source = audioCtx.createBufferSource(); /* * 通过fetch下载音频,responseType设置为'arrayBuffer',我们以arrayBuffer格式接收返回的数据 */ fetch(audioUrl, { method: 'GET', responseType: 'arraybuffer', }).then(res => { return res.arrayBuffer(); }).then(data => { // 处理音频数据 initAudio(data); });
拿到音频数据之后,我们需要利用Web Audio Api,来处理音频数据,实现音频的播放,暂停等操作以及我们后续的波形图绘制。这里简单介绍下,Web Audio Api是一组非常强大的Api,它提供了在Web中控制音频、处理音频的一整套有效通用的系统。它能够允许开发着,控制音频,自选音频源、对音频添加特效,使音频可视化,添加空间效果,添加混响等等。而我们今天要实现的功能,仅仅只用到了其中几个Api,整体流程如下:
// audio 初始化 function initAudio (data) { // 音频数据解码 // decodeAudioData方法接收一个arrayBuffer数据作为参数,这也是为什么前面fetch音频时设置以arrayBuffer格式接收数据 audioCtx.decodeAudioData(data).then(buffer => { // decodeAudioData解码完成后,返回一个AudioBuffer对象 // 绘制音频波形图 drawWave(buffer); // 连接音频源 source.buffer = buffer; source.connect(audioCtx.destination); // 音频数据处理完毕 alert('音频数据处理完毕!'); }); } // web audio 规范不允许音频自动播放,需要用户触发页面事件来触发播放,这里我们增加一个播放按钮,数据处理完毕后点击播放 document.querySelector('#btn').onclick = () => { // 播放音频 source.start(0); }
音频数据通过AudioContext解码后,返回一个AudioBuffer对象,这个对象,保存有音频的采样率、声道、pcm数据等信息。通过getChannelData方法可以获取到音频某个声道的pcm数据。返回的是一个Float32Array对象,数值范围在-1到1之间。音频数据比较庞大,每一秒钟可能包含成千上万的数据,因此我们在做图形绘制时,需要对数据进一步采样。比如,这里我们采用每1000条数据中,取一个最大值(正数)一个最小值(负数)来绘制图形;
// 绘制波形图 function drawWave (buffer) { // buffer.numberOfChannels返回音频的通道数量,1即为单声道,2代表双声道。这里我们只取一条通道的数据 let data = []; let originData = buffer.getChannelData(0); // 存储所有的正数据 let positives = []; // 存储所有的负数据 let negatives = []; // 先每隔100条数据取1条 for (let i = 0; i < originData.length; i += 100) { data.push(originData[i]); } // 再从data中每10条取一个最大值一个最小值 for (let j = 0, len = parseInt(data.length / 10); j < len; j++) { let temp = data.slice(j * 10, (j + 1) * 10); positives.push(Math.max.apply(null, temp)); negatives.push(Math.min.apply(null, temp)); } // 创建canvas上下文 let canvas = document.querySelector('#canvas'); if (canvas.getContext) { let ctx = canvas.getContext('2d'); canvas.width = positives.length; let x = 0; let y = 100; let offset = 0; ctx.fillStyle = '#fa541c'; ctx.beginPath(); ctx.moveTo(x, y); // canvas高度200,横坐标在canvas中点100px的位置,横坐标上方绘制正数据,下方绘制负数据 // 先从左往右绘制正数据 // x + 0.5是为了解决canvas 1像素线条模糊的问题 for (let k = 0; k < positives.length; k++) { ctx.lineTo(x + k + 0.5, y - (100 * positives[k])); } // 再从右往左绘制负数据 for (let l = negatives.length - 1; l >= 0; l--) { ctx.lineTo(x + l + 0.5, y + (100 * Math.abs(negatives[l]))); } // 填充图形 ctx.fill(); } };
读到这里,这篇“Web Audi怎么绘制音频图谱”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。