本文通過4個案例介紹了使用 p5.js 進行音樂可視化的實踐,包括將音頻振幅轉化為圖形、生成波形圖。
承上一篇:vite:初學 p5.js demo 畫圓圈
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); // 基于圓柱基礎高度5pop();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,振幅最高不能超過400let 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 , 鼠標點擊一下就播放音樂。
?參閱:p5.js 交互應用實戰 —— 音樂可視化(案例)