p5.js 交互应用实战 —— 音乐可视化(案例)
案例一 将振幅转化为图形
准备工作:打开编辑器左边菜单,upload mp3音乐素材(不超过5m)
//定义变量
//Sound–声音, amplitude–振幅
let Sound, amplitude;
//1.预读器(新建函数用来读取上传的音频)
function preload(){
Sound = loadSound(‘sound.mp3’);
}
//2.初始化
function setup(){
createCanvas(400,400);
amplitude = new p5.Amplitude();
//将振幅生成线
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(Sound.isPlaying()){
Sound.pause();
}else{
Sound.play();
background(255,255,0);
}
}
截图:
案例二 将振幅转换成波形
let Sound, fft;
//预读器
function preload(){
Sound = loadSound(‘sound.mp3’);
}
//初始化
function setup(){
createCanvas(800,320);
fft = new p5.FFT();
frameRate(20);//变化频率
}
//开始绘制
function draw(){
background(255);
//获取波形
let waveform = fft.waveform();
noFill();
stroke(‘skyblue’);
strokeWeight(2);
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,320);
//line(i,160,i,y);
vertex(x,y);
}
endShape();
}
//按钮控制播放停止
function mousePressed(){
if(Sound.isPlaying()){
Sound.pause();
}else{
Sound.play();
background(255,255,0);
}
}
截图:
案例三 声音交互,麦克风捕获,创建振幅
//mic–麦克风, amp–振幅
let mic, amp, r;
function setup(){
createCanvas(600,600);
background(0);
//调用麦克风和振幅库
mic = new p5.AudioIn();
amp = new p5.Amplitude();
mic.start();
//转换麦克风的振幅
amp.setInput(mic);
}
function draw(){
fill(0,10);
rect(0,0,width,height);
r = map(amp.getLevel(),0,1,20,600);
fill(random(255),random(255),random(255));
ellipse(width/2,height/2,r,r);
}
function mousePressed(){
if(getAudioContext().state!=‘running’){
getAudioContext().resum();
}
}
function touchStarted(){
if(getAudioContext().state!=‘running’){
getAudioContext().resum();
}
}
案例四 综合应用
let Sound,amp,fft
//预读器
function preload(){
Sound = loadSound(‘sound.mp3’);
}
//初始化
function setup(){
createCanvas(400,400);
amp = new p5.Amplitude();
noStroke();
fft = new p5.FFT();
frameRate(20);
}
//开始绘制
function draw(){
background(0,80);
//振幅转换为图形
let level = amp.getLevel();
let r = map(level,0,1,0,150);
fill(random(255),80,80);
ellipse(width/2,height/2,r,r);
//振幅转换为波形
let waveform = fft.waveform();
noFill();
stroke(255,80,80,60);
strokeWeight(2);
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,400);
let angle = map(i,0,1024,0,360);
x = width/2 + cos(angle) * 180;
y = height/2 + sin(angle) * 180;
let r = map(waveform[i],-0.8,0.8,50,220);
x1 = width/2 + cos(angle) * r;
y1 = height/2 + sin(angle) * r;
line(x,y,x1,y1);
}
}
//点击播放暂停
function mousePressed(){
if(Sound.isPlaying()){
Sound.pause();
}else{
Sound.play();
background(255,255,0);
}
}