p5.js:sound(音乐)可视化,动画显示音频高低变化

本文通过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() 方法,并将返回值赋给变量 waveformwaveform() 方法的作用是获取当前音频信号的波形数据。波形数据是音频信号在时域上的表示,它记录了音频信号在不同时间点的振幅值。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 , 鼠标点击一下就播放音乐。

 参阅:p5.js 交互应用实战 —— 音乐可视化(案例)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/984468.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PDF处理控件Aspose.PDF,如何实现企业级PDF处理

PDF处理为何成为开发者的“隐形雷区”&#xff1f; “手动调整200页PDF目录耗时3天&#xff0c;扫描件文字识别错误导致数据混乱&#xff0c;跨平台渲染格式崩坏引发客户投诉……” 作为开发者&#xff0c;你是否也在为PDF处理的复杂细节消耗大量精力&#xff1f;Aspose.PDF凭…

ruo-yi项目启动备忘

ruo-yi项目启动遇到问题备忘 参考文档: 若依 手把手启动 https://blog.csdn.net/qq_43804008/article/details/132950644?utm_mediumdistribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-1-132950644-blog-137337537.235^v43^pc_blog_bottom_…

⭐LeetCode周赛 Q1. 找出最大的几近缺失整数——模拟⭐

⭐LeetCode周赛 Q1. 找出最大的几近缺失整数——模拟⭐ 示例 1&#xff1a; 输入&#xff1a;nums [3,9,2,1,7], k 3 输出&#xff1a;7 解释&#xff1a; 1 出现在两个大小为 3 的子数组中&#xff1a;[9, 2, 1]、[2, 1, 7] 2 出现在三个大小为 3 的子数组中&#xff1a;[3,…

Java 集合框架大师课:性能调优火葬场(四)

&#x1f680; Java 集合框架大师课&#xff1a;性能调优火葬场&#xff08;四&#xff09; &#x1f525; 战力值突破 95% 警告&#xff01;调优就像吃重庆火锅——要选对食材&#xff08;数据结构&#xff09;还要控制火候&#xff08;算法&#xff09;&#x1f336;️ 第一章…

【愚公系列】《Python网络爬虫从入门到精通》045-Charles的SSL证书的安装

标题详情作者简介愚公搬代码头衔华为云特约编辑&#xff0c;华为云云享专家&#xff0c;华为开发者专家&#xff0c;华为产品云测专家&#xff0c;CSDN博客专家&#xff0c;CSDN商业化专家&#xff0c;阿里云专家博主&#xff0c;阿里云签约作者&#xff0c;腾讯云优秀博主&…

蓝桥杯嵌入式组第七届省赛题目解析+STM32G431RBT6实现源码

文章目录 1.题目解析1.1 分而治之&#xff0c;藕断丝连1.2 模块化思维导图1.3 模块解析1.3.1 KEY模块1.3.2 ADC模块1.3.3 IIC模块1.3.4 UART模块1.3.5 LCD模块1.3.6 LED模块1.3.7 TIM模块 2.源码3.第七届题目 前言&#xff1a;STM32G431RBT6实现嵌入式组第七届题目解析源码&…

KUKA机器人:智能制造的先锋力量

在科技日新月异的今天&#xff0c;自动化和智能化已成为推动制造业转型升级的重要引擎。作为全球领先的智能、资源节约型自动化解决方案供应商&#xff0c;KUKA机器人在这一浪潮中扮演着举足轻重的角色。本文将带您深入了解KUKA机器人的发展现状&#xff0c;探索其在智能制造领…

Ateme在云端构建可扩展视频流播平台

Akamai Connected Cloud帮助Ateme客户向全球观众分发最高质量视频内容。 “付费电视运营商和内容提供商现在可以在Akamai Connected Cloud上通过高质量视频吸引观众&#xff0c;并轻松扩展。”── Ateme首席战略官Rmi Beaudouin ​ Ateme是全球领先的视频压缩和传输解决方案提…

OceanBase社区年度之星专访:张稚京与OB社区的双向奔赴

2024年年底&#xff0c;OceanBase社区颁发了“年度之星”奖项&#xff0c;旨在表彰过去一年中为 OceanBase 社区发展作出卓越贡献的个人。今天&#xff0c;我们有幸邀请到这一荣誉的获得者——来自融科智联的张稚京老师&#xff0c;并对他进行了专访。 在过去的一年中&#xf…

如何选择国产串口屏?

目录 1、迪文 2、淘晶驰 3、广州大彩 4、金玺智控 5、欣瑞达 6、富莱新 7、冠显 8、有彩 串口屏&#xff0c;顾名思义&#xff0c;就是通过串口通信接口&#xff08;如RS232、RS485、TTL UART等&#xff09;与主控设备进行通信的显示屏。其核心功能是显示信息和接收输入…

涨薪技术|Kubernetes(k8s)之Service服务

01Service简介 Kubernetes Pod 是有生命周期的&#xff0c;它们可以被创建&#xff0c;也可以被销毁&#xff0c;然而一旦被销毁生命就永远结束。通过 ReplicationController 能够动态地创建和销毁 Pod&#xff08;例如&#xff0c;需要进行扩缩容&#xff0c;或者执行 滚动升…

Quickwit+Jaeger+Prometheus+Grafana搭建Java日志管理平台

介绍 生产服务应用可观测性在当下比较流行的方案&#xff0c;其中出现了大量高性能、开箱即用、易上手的的开源产品&#xff0c;大大丰富了在可观测性领域产品的多样性&#xff0c;本文讲述基于OTLP协议推送Java项目遥测数据&#xff08;日志、指标、链路&#xff09;到后端存储…

「mysql」Mac mysql一路畅通式安装

折腾了一上午&#xff0c;遇到的各种错误&#xff1a; 错误一&#xff1a;安装后&#xff0c;终端执行 mysql 或者执行 mysql -u root -p 时报错&#xff1a; ERROR 1045 (28000): Access denied for user rootlocalhost (using password: YES)错误二&#xff1a;为解决错误一&…

Linux原生异步IO原理与实现(Native AIO)

异步 IO&#xff1a;当应用程序发起一个 IO 操作后&#xff0c;调用者不能立刻得到结果&#xff0c;而是在内核完成 IO 操作后&#xff0c;通过信号或回调来通知调用者。 异步 IO 与同步 IO 的区别如图所示&#xff1a; 从上图可知&#xff0c;同步 IO 必须等待内核把 IO 操作处…

AI编程方法第三弹:让它改错

很多情况下&#xff0c;我们自己还是可以完成代码的&#xff0c;不过会遇到很多错误。在发生错误时&#xff0c;可以充分利用AI编程工具帮助我们调试错误&#xff0c;加快处理速度。当然&#xff0c;对于初学者并不建议&#xff0c;还是等自己掌握了基础知识&#xff0c;再去考…

【论文解读】MODEST 透明物体 单目深度估计和分割 ICRA 2025

MODEST是一种用于透明物体的单目深度估计和分割的方法&#xff0c;来自ICRA 2025。 它通过单张RGB图像作为输入&#xff0c;能够同时预测透明物体的深度图和分割掩码。 由深度图生成点云数据&#xff0c;然后采用GraspNet生成抓取位姿&#xff0c;开展透明物体抓取实验。 论文…

基于SpringBoot的美食信息推荐系统设计与实现(源码+SQL脚本+LW+部署讲解等)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

Unity--Cubism Live2D模型使用

了解LIVE2D在unity的使用--前提记录 了解各个组件的作用 Live2D Manuals & Tutorials 这些文件都是重要的控制动画参数的 Cubism Editor是编辑Live2D的工具&#xff0c;而导出的数据的类型&#xff0c;需要满足以上的条件 SDK中包含的Cubism的Importer会自动生成一个Pref…

2025人工智能AI新突破:PINN内嵌物理神经网络火了

最近在淘金的时候发现基于物理信息的神经网络&#xff08;简称PINN&#xff09;也是个研究热点&#xff0c;遂研读了几篇经典论文&#xff0c;深觉这也是个好发论文的方向&#xff0c;所以火速整理了一些个人认为很值得一读的PINN论文和同学们分享。 为了方面同学们更好地理解…

大模型是如何工作的

近几十年来&#xff0c;人工智能经历了从基础算法到生成式AI的深刻演变。生成式AI通过学习大量数据可以创造出全新的内容&#xff0c;如文本、图像、音频和视频&#xff0c;这极大地推动了AI技术的广泛应用。常见的应用场景包括智能问答&#xff08;如通义千问、GPT&#xff09…