使用canvas绘图音乐频谱示例及技术分析
作者:smallStone
这篇文章主要为大家介绍了使用canvas实现音乐频谱示例及技术分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
正文
看到跳动的音符你难道不想知道它是如何实现的么?开撸!
问:实现这个有什么用呢?
答:装杯用!😥其实这个操作能实现音频效果器。就是主播开麦后大妈声音变成少女,男人声音可以变女声!😱因为音频分析器可以拿到音频的频谱,既可以改变音调啊音色啊什么的就可以实现音频效果器!🐷
不想看我啰嗦的直接看最后,有整体html+js代码,粘贴到你的html页面内,换以下音频资源链接就能看到效果了!
效果图

技术分析
音频加载
在html内增加audio标签。将音乐加载进来。给audio标签增加controls属性用来控制音乐播放。如下:
<html> <body> <audio src="/source/YOU.m4a" controls></audio> </body> </html>
频谱获取
要获取音频的频谱需要使用javascript的AudioContext对象。
var audio = document.querySelector("audio");
let dataArray = new Uint8Array(512);
let analyser = null
audio.onplay = function() {
let audctx = new AudioContext() // 创建音频上下文
let source = audctx.createMediaElementSource(audio) // 创建音频源
analyser = audctx.createAnalyser() // 创建音频分析器
analyser.fftSize = 512 // 设置分析器大小, 必须为2^n次方
// 创建一个数组,用于存放分析器节点数据
// analyser.frequencyBinCount可以拿到傅里叶变换的值,因为傅里叶变换是对称的因此只要一半即可(傅里叶变换请自行搜索)
dataArray = new Uint8Array(analyser.frequencyBinCount)
source.connect(analyser) // 音频源连接到音频分析器
analyser.connect(audctx.destination) // 音频分析器连接到音频输出
}至此我们已经获取到了音频的频谱数据。
频谱可视化
对于高效绘制需要用到画布,既canvas标签,在body内增加canvas标签,并起id为cvs。
<body>
<canvas id="cvs"></canvas>
<audio src="/source/YOU.m4a" controls></audio>
</body>var cvs = document.getElementById("cvs");
var ctx = cvs.getContext("2d");
function initCanvas() {
// 设置canvas宽度为浏览器可视区域
cvs.width = window.innerWidth * devicePixelRatio;
// 设置canvas高度为浏览器可视区域的一半
cvs.height = window.innerHeight / 2 * devicePixelRatio;
}
// 窗口变化时候重新设置canvas宽高
window.onresize = function() {
initCanvas();
}
// 定义draw方法用于绘制频谱
function draw() {
// 使用浏览器自带帧动画函数实现每一帧都绘制。
requestAnimationFrame(draw);
// 清空画布
ctx.clearRect(0, 0, cvs.width, cvs.height);
const len = dataArray.length / 1.2; // 截取频谱绘制长度
const barWidth = cvs.width / len; // 每一根柱子的宽度
ctx.fillStyle = '#c875fc'; // 给柱子填充颜色
// 遍历每一根柱子,设置其位置以及边框。
for (let i = 0; i < len; i++) {
const data = dataArray[i]
const barHeight = data / 255 * cvs.height
const x = i * barWidth
const y = cvs.height - barHeight
drawBorder(x,y,barWidth, barHeight)
ctx.fillStyle = '#8ca86d'
ctx.fillRect(x, y, barWidth, barHeight)
}
}至此基本完成了绘制方面的任务
全部合并后就是以下代码,将以下代码在你本机创建一个html复制进去就可以看到效果(注意把音频资源换成自己的):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>声音波浪</title>
</head>
<style>
#cvs {
border: 1px solid #000;
}
audio {
display: block;
}
</style>
<body>
<canvas id="cvs"></canvas>
<audio src="/source/YOU.m4a" controls></audio>
</body>
<script>
var cvs = document.getElementById("cvs");
var ctx = cvs.getContext("2d");
var audio = document.querySelector("audio");
let isInitAudio = false;
let analyser = null
let dataArray = new Uint8Array(512);
/* 初始化canvas */
function initCanvas() {
cvs.width = window.innerWidth * devicePixelRatio;
cvs.height = window.innerHeight / 2 * devicePixelRatio;
}
window.onresize = function() {
initCanvas();
}
/* 初始化音频 */
function initAudio() {
audio.onplay = function() {
let audctx = new AudioContext() // 创建音频上下文
let source = audctx.createMediaElementSource(audio) // 创建音频源
analyser = audctx.createAnalyser() // 创建音频分析器
analyser.fftSize = 512 // 设置分析器大小, 必须为2^n次方
// 创建一个数组,用于存放分析器节点数据
// analyser.frequencyBinCount可以拿到傅里叶变换的值,因为傅里叶变换是对称的因此只要一半即可
dataArray = new Uint8Array(analyser.frequencyBinCount)
draw()
source.connect(analyser) // 音频源连接到音频分析器
analyser.connect(audctx.destination) // 音频分析器连接到音频输出
let bufferLength = analyser.frequencyBinCount
}
}
function draw() {
requestAnimationFrame(draw);
// 清空画布
ctx.clearRect(0, 0, cvs.width, cvs.height);
analyser.getByteFrequencyData(dataArray)
const len = dataArray.length / 1.2
const barWidth = cvs.width / len
ctx.fillStyle = '#c875fc'
for (let i = 0; i < len; i++) {
const data = dataArray[i]
const barHeight = data / 255 * cvs.height
const x = i * barWidth
const y = cvs.height - barHeight
drawBorder(x,y,barWidth, barHeight)
ctx.fillStyle = '#8ca86d'
ctx.fillRect(x, y, barWidth, barHeight)
}
}
function drawBorder(xPos, yPos, width, height, thickness = 1) {
ctx.fillStyle='#000';
ctx.fillRect(xPos - (thickness), yPos - (thickness), width + (thickness * 2), height + (thickness * 2));
}
function initAll() {
initCanvas();
initAudio()
}
initAll()
</script>
</html>以上就是使用canvas实现音乐频谱示例及技术分析的详细内容,更多关于canvas音乐频谱的资料请关注脚本之家其它相关文章!
