Pixi + Tone 实现简单midi音频可视化

news2024/11/25 6:58:22

在这里插入图片描述

依赖库

  • Pixi.js 是一个前端图形渲染库,使用精灵技术绘制高性能的图形。
  • Tone.js是一个前端音频框架,对web audio api进行了封装,可以快速创建音频样本、音频效果、进行音频分析和音频播放。
  • @tonejs/midi是tonejs的一个插件,可以讲midi文件转化为Tone.js可以解析的json格式。

midi文件解析

首先需要讲midi文件导入紧浏览器,由于浏览器的安全限制,我们只能使用文件选择器讲文件导入。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Midi可视化</title>
</head>
<body>
  <input type="file" id="file">

  <script>
    const input = document.querySelector('#file');
    input.addEventListener('change', (e) => {
      console.log(e.target.files[0]);
    })
  </script>
</body>
</html>

这样就可以拿到Midi文件对应的File对象。
在这里插入图片描述

导入tonejs和tone/midi插件,准备解析File对象。

  <script
  type="text/javascript"
  src="https://unpkg.com/tone@latest/build/Tone.js"
  ></script>
  <script
  type="text/javascript"
  src="https://unpkg.com/@tonejs/midi"
></script>

使用MIDI插件解析File对象。

    // 读取midi文件
    function parseMidi(file) {
      // 创建文件读取器
      const reader = new FileReader();
      // 读取文件
      reader.readAsArrayBuffer(file);
      // 文件读取完成后将文件转化为json对象
      reader.addEventListener('load', (e) => {
        currentMidi = new Midi(e.target.result);
        console.log(currentMidi);
      })
    }

有没有懂设计模式的,可以帮我优化下代码嘛,定义了一个全局变量currentMidi总觉得不舒服。
这个currentMidi中存储了midi文件的音轨,音符,乐器等信息。可以为下面创建合成器和可视化提供数据。
在这里插入图片描述

音频播放

音频使用tonejs创建合成器来播放。
在页面中添加一个按钮并绑定事件,用于播放音频,下面这段代码里有用到Tonejs创建合成器播放声音的代码。

play.addEventListener('click', (e) => {
      console.log(currentMidi);
      // 如果未加载midi文件
      if(!currentMidi) {
        alert('未加载文件');
        return;
      }

      const now = Tone.now() + 0.5; // 获取当前时间
      const synths = [];            // 存储合成器
      // 遍历midi文件中的轨道
      currentMidi.tracks.forEach(track => {
        // 创建合成器作为音轨并连接至出口,音色使用Tonejs的默认音色
        const synth = new Tone.PolySynth(Tone.Synth, {
					envelope: {
            // 声音的生命周期:按下按键 - 渐入 - 攻击阶段 - 衰减阶段 - 衰减结束 - 松开按键 - 声音消逝
						attack: 0.02,     // 渐入时间
						decay: 0.1,       // 攻击阶段(最大音量)持续时间
						sustain: 0.3,     // 衰减结束后的最小声音
						release: 1,       // 从松开按键到声音彻底消失所需的时间
					},
				}).toDestination();
		// 将合成器存储起来,为之后停止播放的功能留下接口。
        synths.push(synth);

        // 遍历轨道中的每个音符
        track.notes.forEach(note => {
          // 合成器发声
          synth.triggerAttackRelease(
						note.name,         // 音名
						note.duration,     // 持续时间
						note.time + now,   // 开始发声时间
						note.velocity      // 音量
					);
        });
      });
    })

合成器
到这里就可以实现MIDI文件的播放了。

可视化

可视化采用pixijs,首先使用npm下载pixijs然后导入。

<script src="../../node_modules/pixi.js/dist/pixi.js"></script>

使用pixijs创建一块画布并挂载到页面上。

const Application = PIXI.Application;  // 应用类,快速创建PIXI应用
    const Sprite = PIXI.Sprite;            // 精灵类
    const Graphics = PIXI.Graphics;        // 图形类
    // 创建应用程序并挂载
    const pixi = new Application({
      width: 1000,
      height: 600,
      backgroundColor: 0x000000
    })
    // pixi.view 代表画布,是一个canvas元素
    document.body.appendChild(pixi.view);

在这里插入图片描述
我们使用灯管类作为每一个音符的可视化。

const config = {
      speed: 1
    }
    // 定义灯光类作为音符的可视化
    class Light extends Graphics {
      constructor(color, height, x) {
        super();
        this.beginFill(color);
        this.drawRect(x, 600, 10, height);
        this.endFill();
        // pixijs的定时器,可以实现每帧执行一次,并且十分稳定
        pixi.ticker.add(() => {
          this.y -= config.speed * 5;
        });
      }
    }

随便创建两个灯管两个试试效果。

// pixi.stage 代表舞台,所有的物体必须挂载在舞台上才可以显示。
pixi.stage.addChild( new Light(0xffffff, 50, 400) );

在这里插入图片描述
成功显示,并且一直向上移动。

之后就是根据解析出来的json对象创建音符。
为了尽可能得跟音频同步减小延时,我们使用Tonejs的音频调度。
在对音符进行遍历时创建这个音符对应的调度任务。

// 在播放按钮的事件中,遍历音符时,创建音频调度,实现音画同步
Tone.Transport.schedule((time) => {
	// 根据音调划分颜色,(其实应该根据轨道来划分的)
	if(note.midi < 65) {
		pixi.stage.addChild(new Light(g.config.leftColor, note.duration * 200 * g.config.speed, (note.midi - 20) * 10))
	} else {
		pixi.stage.addChild(new Light(g.config.rightColor, note.duration * 200 * g.config.speed, (note.midi - 20) * 10))
	}
}, note.time + now);

// 在代码最外层设置音频调度的模式,并启动音频调度。
Tone.context.latencyHint = 'fastest';
Tone.Transport.start();

到这里程序的基本功能就完成了。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Iterator-Generator详解

1 迭代器可迭代对象 2 原生的迭代器对象 3 自定义类的迭代器 4 生成器理解和作用 5 自定义生成器方案 6 异步处理方案解析 迭代器-JavaScript中迭代器&#xff08;了解&#xff09; 给某个数组专门添加一个迭代器的代码。 const names ["abc", "cba"…

诚迈科技子公司智达诚远精耕智能驾驶,为商用落地注入创新力量

近期&#xff0c;工业和信息化部副部长辛国斌在新闻发布会上表示&#xff0c;将启动智能网联汽车准入和上路通行试点&#xff0c;组织开展城市级“车路云一体化”示范应用&#xff0c;将支持L3级及更高级别的自动驾驶功能商业化应用。根据工信部最新消息&#xff0c;《智能网联…

微聊测试报告

文章目录 微聊测试用例功能测试自动化测试注册页面登录页面会话窗口朋友圈界面 界面测试注册页面登录页面会话页面朋友圈页面 兼容性测试PCPad手机浏览器 性能测试安全测试密码保存是否安全SQL注入服务器错发 网络有网弱网断网 ​&#x1f451;作者主页&#xff1a;Java冰激凌 …

Pinia学习笔记 | 入门 - 映射辅助函数

文章目录 Pinia学习笔记简介Pinia是什么 代码分割机制案例1.挂载PiniaVue3Vue2&#xff1a;安装PiniaVuePlugin插件 2.定义store的两种方式options API 和 composition API使用options API模式定义使用composition API模式 2.业务组件对store的使用创建store实例解构访问Pinia容…

Vue学习笔记 之 Svg图标组件的实现步骤

1、安装依赖 首先需要安装svg-sprite-loader依赖&#xff0c;命令如下&#xff0c;这在在学习的过程中&#xff0c;就是因为没有下载该依赖&#xff0c;导致图标一直无法正常显示。 npm install svg-sprite-loader --save-dev --force2、配置svg图片处理规则 通过使用svg-spri…

【嵌入式Linux内核驱动】SPI子系统 | 硬件原理 | 应用编程 | 内核驱动 | 总体框架

1. 硬件原理 1.1 SPI通信协议 SPI&#xff08;Serial Peripheral Interface&#xff09;是由Motorola公司开发的一种通用数据总线 四根通信线&#xff1a;SCK&#xff08;Serial Clock&#xff09;、MOSI&#xff08;Master Output Slave Input&#xff09;、MISO&#xff08…

jmeter主要函数助手功用说明

jmeter中虽然有很多的插件&#xff0c;但是有些需要安装&#xff0c;有些具有一定的局限性。函数助手是一个快捷的工具库。下面记录一下函数助手中一些主要的函数的使用方法。 注&#xff1a;不内容中所有的实例均基于3.2记录 1、_BeanShell 表达式请求值后的值&#xff1a;可…

Hadoop之Hive安装

一、嵌入模式安装 1、下载Hive安装包 https://archive.apache.org/dist/hive/hive-1.2.1/ 2、上传至/root/export/software/ rz apache-hive-1.2.1-bin.tar.gz 3、解压 tar apache-hive-1.2.1-bin.tar.gz -C /root/export/servers/ cd /root/export/servers/apache-hive-1.2.…

openGauss学习笔记-09 openGauss 简单数据管理-创建数据库

文章目录 openGauss学习笔记-09 openGauss 简单数据管理-创建数据库9.1 语法格式9.2 参数说明9.3 示例 openGauss学习笔记-09 openGauss 简单数据管理-创建数据库 数据库安装完成后&#xff0c;默认生成名称为postgres的数据库。您需要自己创建一个新的数据库。 9.1 语法格式…

【Docker】Docker高级网络(NetWork)

【Docker】Docker高级网络(NetWork) 文章目录 【Docker】Docker高级网络(NetWork)1. 概述2. 网络2.1 网桥类型2.2 创建网络自定义桥2.3 查看所有网络2.4 查看特定网络的细节2.5 删除特定网络2.6 多个容器使用指定网络 参考文档&#xff1a;高级网络配置 Docker – 从入门到实践…

手机pdf怎么转换为图片?看看这几个转换方法

手机pdf怎么转换为图片&#xff1f;将手机图片转为PDF有很多好处。首先&#xff0c;PDF文件通常比图片文件更小&#xff0c;可以节省手机存储空间。其次&#xff0c;PDF文件可以更轻松地与他人共享&#xff0c;并且可以在不同设备和操作系统上打开。最后&#xff0c;将图片转换…

superheat | 超级简单的热图绘制解决方案!~(二)(聚类和注释图的添加~)

1写在前面 前面写了superheat的教程&#xff0c;今天写一下第二波&#xff0c;如何进行聚类以及添加注释图吧。&#x1f929; 分分钟提升你的heatmap的颜值哦&#xff01;~&#x1f970; 2用到的包 # devtools::install_github("rlbarter/superheat")library(superhe…

二叉树(中)+Leetcode每日一题——“数据结构与算法”“剑指Offer55-I. 二叉树的深度”“100.相同的树”“965.单值二叉树”

各位CSDN的uu们你们好呀&#xff0c;今天继续数据结构与算法专栏中的二叉树&#xff0c;下面&#xff0c;让我们进入二叉树的世界吧&#xff01;&#xff01;&#xff01; 二叉树&#xff08;上&#xff09;——“数据结构与算法”_认真学习的小雅兰.的博客-CSDN博客 二叉树链…

TypeScript 中对【泛型】的定义使用方式解读

目录 泛型函数多个泛型参数泛型约束泛型别名泛型接口泛型类 泛型&#xff08;Generics&#xff09;是指在定义函数、接口或类的时候&#xff0c;不预先指定具体的类型&#xff0c;而在使用的时候再指定类型的一种特性。使用泛型 可以复用类型并且让类型更加灵活 泛型实现类型参…

Pycharm安装 leetcode 插件

目录 本节演示Pycharm安装 leetcode 插件做算法题 打开设置&#xff1a; 点击插件&#xff1a; 搜索leetcode并安装&#xff1a; 点这里的 leetcode&#xff1a; 初次使用点这里&#xff1a; 这里输入账号和密码&#xff1a; 点击确定后还是点登录&#xff1a; 登…

【MySQL】SQL入门(一)

&#x1f697;MySQL学习起始站~ &#x1f6a9;本文已收录至专栏&#xff1a;数据库学习之旅 ❤️每章节附章节思维导图&#xff0c;文末附全文思维导图&#xff0c;感谢各位点赞收藏支出~ 一.引入 (1) SQL分类 SQL语句&#xff0c;根据其功能&#xff0c;主要分为四类&#x…

巧妙使用 CSS 渐变来实现波浪动画

目录 一、波浪的原理 二、曲面的绘制 三、波浪动画 四、文字波浪动画 五、总结一下 参考资料 之前看到coco[1]的这样一篇文章&#xff1a;纯 CSS 实现波浪效果&#xff01;[2]&#xff0c;非常巧妙&#xff0c;通过改变border-radius和不断旋转实现的波浪效果&#xff0c…

网络安全—全知识点解析(课程学习笔记)

概括来说&#xff0c;网络安全课程的主要内容包括&#xff1a; 安全基本知识 应用加密学 协议层安全 Windows安全&#xff08;攻击与防御&#xff09; Unix/Linux安全&#xff08;攻击与防御&#xff09; 防火墙技术 入侵监测系统 审计和日志分析 下面分别对每部分知识介绍相应…

Stable Diffusion - ControlNet 插件中扩展局部重绘 InpaintOnly + LaMa 算法与应用

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/131643131 LaMa: https://github.com/advimman/lama Paper: Resolution-robust Large Mask Inpainting with Fourier Convolutions LaMa: Large…

哇~~真的是你呀!今天是在LINUX上简单部署LAMP平台。

目录 一、概述 二、PHP安装配置 三、安装 四、启动 五、书写测试页面 六、客户端访问 七、安装论坛 一、概述 LAMP组成&#xff1a; &#xff08;1&#xff09; Linux 其他组件的平台 &#xff08;2&#xff09;Apache提供web服务 &#xff08;3&#xff09;MySQL|Ma…