本文通过4个案例介绍了使用 p5.js 进行音乐可视化的实践,包括将音频振幅转化为图形、生成波形图。
cd p5-demo
copy .\node_modules\p5\lib\p5.min.js .
copy .\node_modules\p5\lib\addons\p5.sound.min.js .
在 p5.js 里,FFT()
是 p5.FFT
类的构造函数,p5.FFT
是 p5.sound
库中的一个重要类,它代表快速傅里叶变换(Fast Fourier Transform,FFT)。FFT 是一种在信号处理领域广泛使用的算法,主要用于将时域信号转换为频域信号,通过它能够分析信号在不同频率上的能量分布情况。
作用
在音频可视化的场景中,p5.FFT
可把音频信号从时域转换为频域,让你能获取音频在不同频率下的振幅信息,进而根据这些信息实现音频可视化效果,比如绘制频谱图、波形图等。
用法
在使用 p5.FFT
时,一般先创建一个 p5.FFT
对象,然后在 draw()
函数中调用其 analyze()
方法来获取音频频谱数据。
编写 p5_audio_vis.html 如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>p5.js Audio Visualization</title>
<script src="p5.min.js"></script>
<script src="p5.sound.min.js"></script>
</head>
<body>
<script>
let song; // 音乐
let fft; // 快速傅里叶变换
//1.预读器(新建函数用来读取音频文件)
function preload() {
// 请替换为你自己的音频文件路径
song = loadSound('your_audio_file.mp3');
}
//2.初始化
function setup() {
createCanvas(400, 400);
fft = new p5.FFT();
// 图形一般由填充色和边框两部分组成;noStroke()函数可以关闭边框的绘制
noStroke();
}
//3.开始绘制
function draw() {
background(0); // spectrum 波谱、频谱
let spectrum = fft.analyze();
noStroke();
fill(255, 0, 255);
for (let i = 0; i < spectrum.length; i++) {
let x = map(i, 0, spectrum.length, 0, width);
let h = -height + map(spectrum[i], 0, 255, height, 0);
rect(x, height, width / spectrum.length, h);
}
}
//4.点击按钮播放/停止
function mousePressed(){
if (song.isPlaying()){
song.pause();
} else {
song.play();
}
}
</script>
</body>
</html>
运行 npm run dev
访问 http://localhost:5173/p5_audio_vis.html , 鼠标点击一下就播放音乐。
在 p5.js 中,下面这两行代码的含义如下:
fft = new p5.FFT();
这行代码创建了一个 p5.FFT
对象。p5.FFT
是 p5.sound
库中的一个类,它代表快速傅里叶变换(Fast Fourier Transform,FFT)。快速傅里叶变换是一种高效的算法,能够将时域信号转换为频域信号。在音频处理和可视化的场景中,使用 p5.FFT
对象可以分析音频信号在不同频率上的能量分布情况。这里没有给 p5.FFT
的构造函数传入参数,所以它会使用默认的参数设置,默认平滑度(smoothing
)为 0.8,默认频率区间数量(bins
)为 1024。
waveform = fft.waveform();
这行代码调用了 p5.FFT
对象的 waveform()
方法,并将返回值赋给变量 waveform
。waveform()
方法的作用是获取当前音频信号的波形数据。波形数据是音频信号在时域上的表示,它记录了音频信号在不同时间点的振幅值。waveform()
方法返回一个数组,数组中的每个元素代表了音频信号在某个时间点的振幅,取值范围通常在 -1 到 1 之间。
编写 p5_waveform.html 如下
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>p5 audio necklace demo</title>
<script src="p5.min.js"></script>
<script src="p5.sound.min.js"></script>
</head>
<body>
<script>
let song;
let fft; // 快速傅里叶变换
let waveform; // 波形数据
function preload() {
// 请替换为你自己的音频文件路径
song = loadSound('your.mp3');
}
function setup() {
createCanvas(400, 400);
fft = new p5.FFT();
}
function draw() {
background(0);
waveform = fft.waveform();
stroke(255);
strokeWeight(2);
noFill();
beginShape();
for (let i = 0; i < waveform.length; i++) {
let x = map(i, 0, waveform.length, 0, width);
let y = map(waveform[i], -1, 1, 0, height);
vertex(x, y);
}
endShape();
}
function mousePressed(){
if (song.isPlaying()){
song.pause();
} else {
song.play();
}
}
</script>
</body>
</html>
运行 npm run dev
访问 http://localhost:5173/p5_waveform.html , 鼠标点击一下就播放音乐。
编写 p5_audio_necklace.html 如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>p5 audio necklace demo</title>
<script src="p5.min.js"></script>
<script src="p5.sound.min.js"></script>
</head>
<body>
<script>
const soundPaths = ["your.mp3"];
let fft; // 快速傅里叶变换
let waveform; // 波形
let stars = [];
function preload()
{
sound = loadSound(soundPaths);
}
function setup()
{
createCanvas(640,480,WEBGL); // 创建三维画板
colorMode(HSB); // 颜色体系切换
fft = new p5.FFT();
waveform = fft.waveform();
sound.amp(0.8); // 控制音量
}
function draw()
{
background(255);
orbitControl();
waveform = fft.waveform(); // 计算每一次刷新的音乐段振幅
rotateX(PI/3);
let r = width * 0.3;
for(let a = 0;a < 2 * PI;a += PI/25)
{
let index = int(map(a, 0, 2*PI, 0, 1024));
let curH = abs(300 * waveform[index])
// 需要注意图像绘制原点在电脑屏幕正中央
let x = r * cos(a);
let y = r * sin(a);
push();
translate(x,y,curH/2);
rotateX(PI/2);
let c1 = color(150,200,200);
let c2 = color(200,100,160);
let rate = map(a, 0, 2*PI, 0, 0.9);
let col = lerpColor(c1,c2,rate);
stroke(col);
cylinder(10, 5 + curH); // 基于圆柱基础高度5
pop();
for(let k = 0; k < 10; k++)
{
// 振幅越小,创建粒子的概率就会越小
// 粒子运动的速度和圆柱的高度大小正相关,即振幅越大,粒子运动速度越快
if(random(0.01,1) < waveform[index])
{
// console.log(waveform[index]);
stars.push(new star(x, y, 5 + curH, col));
}
}
}
for(let i = 0; i < stars.length; i++)
{
stars[i].move();
stars[i].show();
// console.log(stars[i].z);
if (stars[i].z > 500)
{
stars.splice(i,1); // 让粒子到一定时间慢慢被删除
}
}
}
function star(x, y, z, col)
{
this.x = x + random(-2,2);
this.y = y + random(-2,2);
this.z = z;
this.col = col;
this.life = 500;
this.speedX = random(-0.3,0.3);
this.speedY = random(-0.3,0.3);
this.speedZ = 0.05 + (z - 5) / 15;
this.move = function()
{
this.z += this.speedZ;
this.x += this.speedX;
this.y += this.speedY;
this.life -= 1;
};
this.show = function()
{
push();
let a = map(this.life, 0, 500, 0, 1);
stroke(hue(this.col), saturation(this.col),brightness(this.col));
strokeWeight(1);
point(this.x, this.y, this.z);
pop()
};
}
function mousePressed(){
if (sound.isPlaying()){
sound.pause();
} else {
sound.play();
}
}
</script>
</body>
</html>
运行 npm run dev
访问 http://localhost:5173/p5_audio_necklace.html , 鼠标点击一下就播放音乐。
参考:基于p5.js和ml5.js库的“音乐可视化+手势交互控制”创意网页制作
编写 p5_sound_vis.html 如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>p5.js Sound Visualization</title>
<script src="p5.min.js"></script>
<script src="p5.sound.min.js"></script>
</head>
<body>
<script>
//定义变量
let song; // 声音
let amplitude; // 振幅
//1.预读器(新建函数用来读取音频文件)
function preload(){
// 请替换为你自己的音频文件路径
song = loadSound('your.ogg');
}
//2.初始化
function setup(){
createCanvas(400,400);
amplitude = new p5.Amplitude();
//noStroke()函数可以关闭边框的绘制
noStroke();
}
//3.开始绘制
function draw(){
background(0.5);
//自由填充颜色
fill(255,random(255),random(255));
//映射振幅,并转换成图形
let level = amplitude.getLevel();
//振幅是0-1的,画布为400x400,振幅最高不能超过400
let r = map(level,0,1, 0,400);
ellipse(width/2, height/2, r, r);
}
//4.点击按钮播放/停止
function mousePressed(){
if(song.isPlaying()){
song.pause();
} else {
song.play();
}
}
</script>
</body>
</html>
运行 npm run dev
访问 http://localhost:5173/p5_sound_vis.html , 鼠标点击一下就播放音乐。