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

在这里插入图片描述

依赖库

  • 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对象。

  <scripttype="text/javascript"src="https://unpkg.com/tone@latest/build/Tone.js"></script><scripttype="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.hqwc.cn/news/22931.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决小程序 scroll-view 里面的image有间距、小程序里面的图片之间有空隙的问题。

1&#xff09;小程序 image跟view标签上下会有间隙&#xff0c;解决方法如下&#xff1a; 在image那里设置vertical-align:top/bottom/text-top/text-bottom 原因&#xff1a;图片文字等inline元素默许是跟父级元素的baseline对齐&#xff0c;而baseline又和父级底边有必定间距…

http1.0、http1.1 http 2.0

HTTP/1.0是无状态、无连接的应用层协议。 无连接 无连接&#xff1a;每次请求都要建立连接&#xff0c;需要使用 keep-alive 参数建立长连接、HTTP1.1默认长连接keep-alive   无法复用连接&#xff0c;每次发送请求都要进行TCP连接&#xff0c;TCP的连接释放都比较费事&…

【测试开发】测试用例的设计方法

目录 一. 测试用例的基本要素 二. 测试用例的设计方法 1. 测试用例设计的万能公式 水杯测试用例 2. 基于需求的设计方法 邮箱注册测试用例 3. 等价类方法 有效等价类和无效等价类 等价类思想设计测试用例步骤 4. 边界值方法 边界值思想设计测试用例步骤 5. 判定表方法…

120、仿真-51单片机温湿度光照强度C02 LCD1602 报警设计(Proteus仿真+程序+元器件清单等)

方案选择 单片机的选择 方案一&#xff1a;STM32系列单片机控制&#xff0c;该型号单片机为LQFP44封装&#xff0c;内部资源足够用于本次设计。STM32F103系列芯片最高工作频率可达72MHZ&#xff0c;在存储器的01等等待周期仿真时可达到1.25Mip/MHZ(Dhrystone2.1)。内部128k字节…

基于ChatGPT上线《你说我猜》小游戏

摘要 AIGC、GPT、休闲小游戏三者可以怎么结合&#xff1f; AIGC、GPT与小游戏的结合为游戏体验带来了新的可能性。AIGC&#xff08;Artificial Intelligence Game Content&#xff09;作为一种人工智能技术&#xff0c;可以自动生成任务、剧情和角色对话等游戏元素&#xff0c…

【嵌入式Qt开发入门】Qt如何网络编程——建立TCP通信服务端(附项目代码)

TCP 简介 TCP 协议&#xff08;Transmission Control Protocol&#xff09;全称是传输控制协议是一种面向连接的、可靠的、 基于字节流的传输层通信协议。 TCP 通信必须先建立 TCP 连接&#xff0c;通信端分为客户端和服务端。服务端通过监听某个端口来监听是否有客户端连接到来…

Java正则表达式MatchResult的接口、Pattern类、Matcher类

Java正则表达式MatchResult的接口 java.util.regex.MatchResult接口表示匹配操作的结果。 此接口包含用于确定与正则表达式匹配的结果的查询方法。可以看到匹配边界&#xff0c;组和组边界&#xff0c;但不能通过MatchResult进行修改。 接口声明 以下是java.util.regex.Matc…

Flask结合gunicorn和nginx反向代理的生产环境部署及踩坑记录

个人博客&#xff1a;https://xzajyjs.cn 前言 之前自己写的flask使用gunicorn上线生产环境没有什么问题&#xff0c;但是最近搭建了一个现成的flask项目&#xff0c;当使用python直接运行时不会有问题&#xff0c;而使用gunicorn时则会出现一些问题。 部署过程 运行测试 这…

XUbuntu22.04之解决蓝牙鼠标不停掉线问题(追凶过程)(一百八十五)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

JDY-31 蓝牙传输模块的使用、调试和传输

JDY-31 蓝牙基于蓝牙 3.0 SPP 设计&#xff0c;这样可以支持 Windows、Linux、android 数据透传&#xff0c; 工作频段 2.4GHZ&#xff0c;调制方式 GFSK&#xff0c;最大发射功率 8db&#xff0c;最大发射距离 30 米&#xff0c;支持用户通过 AT 命令修改设备名、波特率等指令…

2023年Mac上有哪些优质的工具(一)

Downie 4 专门用来下载视频的&#xff0c;各大视频网站上的视频只要粘贴地址就可以直接下载&#xff0c;并且可以选择清晰度&#xff0c;再也不用受百度云的气了&#xff0c;下载速度非常快&#xff0c;让工作效率大大提高。 Xmind 大家熟知的一款思维导图软件&#xff0c;他…

亚马逊云科技,加速生成式AI的落地

编辑&#xff1a;阿冒 设计&#xff1a;沐由 “展望今天的世界&#xff0c;在机遇之外&#xff0c;更多事后我们看到的是前所未有的巨大挑战。事实证明&#xff0c;惟有通过创新、专注创新&#xff0c;方能挖掘和发现更多的增长机会。” 在2023亚马逊云科技中国峰会的第二天&am…