傅里叶变换音频可视化_快速上手网易云音乐可视化
作者:Sanpeier
https://juejin.im/post/5dd88289e51d4523564243da
什么是音频可视化
音频可视化,顾名思义,就是通过获取音频的波形、频率和其他来自音频的数据转换成图像,再到屏幕上显示出来。通过它,我们能够制作一些炫酷的前端音乐界面。
下面,我将分析一个来自云音乐技术团队的音频可视化开发案例,快速帮助小白,制作自己喜欢的炫酷的音频可视化界面。
先上图
想开发这么一个炫酷的音频界面,我们可以先来聊聊 canvas
canvas是什么
canvas是HTML5中用于图形绘制的容器元素,它通常通过JavaScript脚本来完成图形绘制。要完成我们下面的音频可视化开发,我们可以借组结构canvas的几个方法,下面将通过开发一个页面倒计时的小案例来帮助初学者了解canvas的一些属性和方法。
先上代码
<canvas id="myCanvas"> canvas> <script> const canvas = document.getElementById('myCanvas'); var ctx = canvas.getContext('2d'); ctx.fillStyle = 'red'; ctx.font = "50px Verdana"; let dis = 550; let i = 10; function animation(){ requestAnimationFrame(function(){ if(dis >= 0){ --dis; if(dis%50 == 0 ){ ctx.clearRect(0,0,300,150); ctx.fillText(i--,100,100); } animation(); } }); } animation();script>
我们在html
页面创建一个canvas
画布元素并设置id为myCanvas
,它的默认大小是300*150,创建好了这块画布,接下来我们就能在JavaScript脚本中绘制图形了。
先通过getElementById()
找到这个元素,然后创建canvas对象ctx
并设置填充色为红色,字体为Verdana,大小为50px,设置dis
变量用于条件控制,再定义一个i
变量用于显示倒计时数字,然后我们就可以开始在我们的画布里绘制倒计时数字了。
创建一个animation
函数,在这个函数里面,我们使用了一个html5专门用于请求动画的APIrequestAnimationFrame
请求动画帧,相比于定时器setTimeout
,它不会引起丢帧、丢帧,看起来更加流畅。
在requestAnimationFrame
里面,先设置刷帧条件dis>=0
,dis
每次减一,总共550次,再设置条件为每50次执行一次绘制操作,在每次绘制之前,通过clearRect(x,y,width,height)
方法将画布上给定矩形清空,它的4个参数分别表示要清除的矩形左上角的x,y坐标,以及要清空矩形的宽度和高度,单位以像素计算。然后再通过fillText()
画布指定位置绘制倒计时数字,该方法接收四个参数:text
输出的文本,x
绘制文本的x坐标,y
绘制文本的y坐标,注意:这两个值都是相对于画布,最后一个参数maxWidth
表示允许文本的最大宽度,它是一个可选参数。
接着我们通过递归的方式调用animation()
函数直到倒计时结束,最后在外部调用一下animation()
函数,至此,一个简单的倒计时界面完成。我们还可以给canvas
通过innerWidth
和innerHeight
设置
画布大小。
canvas
可以绘制各种图形,更多内容请自行参看canvas
内容
聊完了canvas
,接下来就是我们的正题了。
Web Audio
在开始之前,我们还需要了解什么是Web Audio。
Web Audio 是 Web 端处理和分析音频的一套 API 。它可以使用户在音频上下文中进行音频操作,具有模块化路由的特点,它也使我们能够控制音频的空间化。
通过Web Audio,我们能够实现取数据和映射数据两个过程,下面我们将实现这两个过程。
项目实现
我们先在页面创建一个canvas
元素和一个audio
标签以及一个用于作播放按钮的a
标签。
然后在JavaScript里面获取audio
和a
这两个元素,并给a
标签设置单击事件。
var btn = document.getElementById('play-btn'); var audio = document.getElementById('audio'); btn.addEventListener('click',function(){ btn.style.display = 'none'; audio.play(); onloadAudio(); })
在onLoadAudio()
函数里面,我们先获取canvas
元素,设置它占满整个页面,再创建canvas
的对象。
var canvas = document.getElementById('canvas'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; var ctx = canvas.getContext('2d');
创建 **AudioContext **对象,用来控制它所包含的节点的创建,以及音频处理、解码操作的执行。
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
通过 createAnalyser()
方法创建 **AnalyserNode **用来获取音频时间和频率数据,实现音频数据可视化。
var analyser = audioCtx.createAnalyser(); analyser.fftSize = 512;
fftSize 在 MDN 里面介绍是快速傅里叶变换的一个参数,取值必须是从32到32768范围内的2的非零幂,默认值为2048,在这里我们取512。另外,fftSize 的值决定了 frequencyData 的长度。
将音频节点关联到 AudioContext上,作为整个音频分析的输入。
我们采用MediaElementAudioSourceNode 将节点作为输入源,并将音频关联到分析器,再将分析器关联到输出设备。
var source = audioCtx.createMediaElementSource(audio); source.connect(analyser); analyser.connect(audioCtx.destination);
接下来获取频率数组。
var bufferLength = analyser.frequencyBinCount; var dataArray = new Uint8Array(bufferLength);
frequencyBinCount()
的值是 fftSize 取值的一半,所以这里的 Uint8Array() 数组的长度就是256。
然后设置音柱的宽度,而高度只定义变量而不赋值,留在后面通过dataArray[]
数组动态设置
var barWidth = WIDTH / bufferLength*1.5; var barHeight;
绘制音柱
定义一个 renderFrame()
函数用于绘制音柱,并且每次绘制之前都先将整个画布清除,然后更新频率数组。
ctx.clearRect(0,0,WIDTH,HEIGHT); analyser.getByteFrequencyData(dataArray);
通过for
循环里面设置每一个矩形的高度,再根据高度设置一个背景色,然后绘制矩形,并填充背景颜色。然后通过递归的方式调用函数。
barHeight = dataArray[i]; var r = barHeight + 25 * (i / bufferLength); var g = 250 * (i / bufferLength); var b = 50; ctx.fillStyle = "rgb(" + r + "," + g + "," + b + ")"; ctx.fillRect(x,HEIGHT-barHeight,barWidth,barHeight); x += barWidth+2;
最后,运行代码,体验属于你的可视化音乐吧。
小结
本文简单介绍了 canvas 的使用和如何通过 Web Audio 的相关 API 获取音频的频率数据。
然而 canvas
和 Web Audio
的用处远远不止于此,读者还可以发挥想象力和创造力,开发出更多有意思的项目。
附上项目源码:
https://github.com/anpeier/lesson_shuidi/tree/master/html5/visualize
-------- END ---------
推荐阅读
(点击标题可跳转阅读)
十款 Windows 下必装软件,大大增强工作幸福
漫画:什么是 HTTPS 协议?
又一个框架来了!被称为要取代 React , vue ,Aangular !
朕已阅
傅里叶变换音频可视化_快速上手网易云音乐可视化相关推荐
- python爬取网易云音乐_爬取网易云音乐评论(一)——用python执行JS脚本
抓包分析 可以发现网页是post请求,表单数据有两个参数params和encSecKey,应该是经过js加密所得 因此在 Initiator 栏里找到对应的js,也就是core...js,点击打开查看 ...
- 解锁网易云音乐小工具_什么?网易云音乐又变灰了
目前音乐市场主要有三大巨头:酷狗音乐,QQ音乐,网易云音乐.QQ音乐与网易云音乐进入市场都较晚,但是网易云音乐凭借灵活的音乐社交玩法积累了非常多的用户,而QQ音乐凭借着有钱优势,购买了很多音乐版权,网 ...
- python3爬取网易云歌单数据清洗_实例 | 使用网易云音乐数据演示数据整合与数据清洗...
作者 | 小F 来源 | 法纳斯特(walker398) 数据整合是对数据进行行列选择.创建.删除等操作. 数据清洗则是将整合好的数据去除其中的错误和异常. 本文利用之前获取的网易云音乐用户数据,来简 ...
- python爬虫网易云音乐评论再分析_爬取网易云音乐的评论后,竟有这种发现!
原标题:爬取网易云音乐的评论后,竟有这种发现! 作者 | 志颖 责编 | 胡巍巍 用过网易云音乐听歌的朋友都知道,网易云音乐每首歌曲后面都有很多评论,热门歌曲的评论更是接近百万或者是超过百万条. 现在 ...
- 网易云音乐爬虫 数据可视化分析
网易云音乐爬虫 & 数据可视化分析 1. 数据爬取 1.1 评论爬取 1.2 用户信息爬取 2 数据清洗 & 可视化 歌评文本分析 个人博客:Archiew's blog 源码:htt ...
- 带你手把手撸一个网易云音乐首页(上篇)
标题前言 Hello,大家好,近期我一直在学习用 Swift 编码,由于之前很多项目我都是用 OC 实现的,所以导致我现在对 Swift 还是处于一个学习的阶段中.为了提高自己的学习效率,每次我都会为 ...
- 网易云信联手网易云音乐,“一起听”创新音乐社交体验
还记得"我的耳机分你一半"的感觉吗? 学生时代,教室里.操场边,抑或是上下学的公交车站,我们都曾与好朋友分享过同一副耳机,你的右耳,他的左耳,两只耳朵一起聆听着同一段属于青春的旋律 ...
- 矿小助 全局主题 | 一个插件实现网易云音乐主题效果 | Flutter
矿小助拥有三种主题,实现起来非常复杂,总结起来就更不用说了,头皮发麻QAQ. 因此,花了半天时间将其拆分出来,做成插件,开源给大家使用.具体的细节大家自己研究吧(溜). 第一次做插件,难免考虑不周,还 ...
- python可视化分析网易云音乐评论_网易云音乐热门评论api分析
网上有现成的例子我就扒过来了!! title: 网易云评论api分析 date: 2018-12-24 20:54:46 tags: [python] 网易云音乐是个好地方,里面各个都是人才,特别是评 ...
最新文章
- 区块链技术特点之去中心化特性
- windows下本地或者远程连接MYSQL数据库,报1130错误的解决方法
- golang interface 转 int string slice struct 类型
- NYOJ 589 糖果
- Android—内存泄漏、GC及LeakCanary源码解析
- 了解ThreadLocal背后的概念
- 基于ubuntu13.04搜狗输入法安装方法
- Cracking the Coding Interview 6.5
- 生命周期 用户可以操作dom_当面试官问:能否介绍下Vue生命周期时,该如何回答...
- 该设备或资源(Web 代理)未设置为接受端口1080上的连接
- Ext3文件读写流程概述
- sql 2005性能调优
- Jeecg-Boot前后端分离版
- Windows多媒体开发框架介绍
- build-up to Ajax v,to build up是什么意思
- 虚拟服务器的磁盘合并,磁盘管理怎么合并分区
- 与化学相关的计算机应用情况,计算机化学的发展、应用与展望
- html 表格 选择,html表格选择与colspan或rowspan
- CCNA-NAT协议 静态NAT 动态NAT(多对多) PAT(多对一) 内网与外网之间的通信 GNS3实验验证
- maya导出带有alpha通道的动画
热门文章
- Qt QPushButton圆形图片设置为背景
- python和c混合编程 gil_终于搞明白python与gil
- 关闭笔记本显示器指定组合键才能打开_笔记本外接显示器怎么设置 笔记本外接显示器设置方法【详解】...
- ffmpeg 硬件解码rtsp流_树莓派使用硬件加速视频转码
- Linux IPC / 分类
- Tiniux 3.0 / Memory.c / OSMemFree
- 启明云端分享|ESP32-C3(ESP32C3MINI1)使用的RISC与CISC有什么区别
- 解决方法|ESP8266环境搭建出现 usrbinenv bashr :没有那个文件或目录
- “云智一体“全场景智能视频技术与应用解析白皮书下载申请
- 如何洞察行业中的应用场景?(上篇)