当前位置: 首页 > news >正文

js 选择一个音频文件,绘制音频的波形,从右向左逐渐前进。

选择一个音频文件,绘制波形,从右向左逐渐前进。
在这里插入图片描述

在这里插入图片描述

完整代码:

<template><div><input type="file" ="handleFileChange" accept="audio/*" /><button ="stopPlayback" :disabled="!isLoaded">停止</button><canvas ref="canvas" width="1201" height="211"></canvas></div>
</template><script>
import axios from "axios";export default {data() {return {// audioUrl:"http://121.41.225.74:9091/mintti/app/storage/newFile/b26uvk9ipd8n5iop1lzs.wav",audioUrl: "http://121.41.225.74:9091/mintti/app/storage/newFile/c19xqqqtd8ywqyaf8gno.wav",// audioUrl: "http://121.41.225.74:9091/mintti/app/storage/newFile/d3msxipdfxrbyijm3ys0.wav",// audioUrl:"http://121.41.225.74:9091/mintti/app/storage/newFile/xm456t9dptsrigxye84q.wav",dataArray: [],isPlaying: false,isLoaded: false,drawInterval: 200, // 设置绘制的时间间隔(单位:毫秒)drawIntervalId: null,fileData: new Int8Array(0),index: 0,mWidth: 0,mHeight: 0,}},mounted() {const ctx = this.$refs.canvas.getContext('2d')this.drawGrid(ctx)this.downloadAudio()},methods: {// 下载音频文件downloadAudio() {axios({method: 'get',url: this.audioUrl,responseType: 'arraybuffer'}).then(res => {if (!res) {return;}console.log("decodeAudioData")this.loadAudio(res.data)}).catch(error => {console.error('下载音频时出错:', error);});;},handleFileChange(event) {this.isLoaded = falseconst file = event.target.files[0]this.stopPlayback()const reader = new FileReader();reader.onload = (e) => {console.log("onLoad")this.loadAudio(e.target.result)};reader.readAsArrayBuffer(file);},loadAudio(res) {this.dataArray = []this.isLoaded = truethis.index = 0;// 获取文件的前 100 个字节this.fileData = new Int8Array(res);this.refreshData()this.drawIntervalId = setInterval(() => {console.log("定时器执行了")this.refreshData()}, this.drawInterval)//循环读取},refreshData() {let i = this.indexconsole.log("文件总长度:" + this.fileData.byteLength + ",,i=" + i)if (i * 1600 + 44 > this.fileData.byteLength) {clearInterval(this.drawIntervalId)return}const byteArray = this.fileData.slice(i * 1600 + 44, (i + 1) * 1600 + 44);// 创建一个新的 Uint16Array,长度为 byteArray 的一半let shortArray = new Int16Array(byteArray.length / 2)//遍历 byteArray,将每两个字节合并成一个短整型for (let i = 0; i < byteArray.length; i += 2) {shortArray[i / 2] = (byteArray[i] & 0xFF) | (byteArray[i + 1] & 0xFF) << 8;}const step = 10;for (let i = 0; i < shortArray.length; i += step) {// console.log(i + "文件short值:" + shortArray[i])if (this.mWidth > 0 && this.dataArray.length >= this.mWidth) {this.dataArray.shift()}this.dataArray.push(shortArray[i])}this.isPlaying = truethis.draw2();this.index += 1;},stopPlayback() {console.log("停止播放-stopPlayback")this.isPlaying = falseclearInterval(this.drawIntervalId)const ctx = this.$refs.canvas.getContext('2d')ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)this.drawGrid(ctx)},draw2() {if (!this.isPlaying) {return}// console.log('开始绘图-draw')const ctx = this.$refs.canvas.getContext('2d')ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)this.drawGrid(ctx)this.drawWaveform(ctx)},drawGrid(ctx) {const { width, height } = ctx.canvasthis.mWidth = ctx.canvas.widththis.mHeight = ctx.canvas.heightctx.strokeStyle = '#ccc'ctx.lineWidth = 1for (let i = 0; i < height; i += 10) {ctx.beginPath()ctx.moveTo(0, i)ctx.lineTo(width, i)ctx.stroke()}for (let j = 0; j < width; j += 10) {ctx.beginPath()ctx.moveTo(j, 0)ctx.lineTo(j, height)ctx.stroke()}},drawWaveform(ctx) {ctx.beginPath()ctx.lineWidth = 1ctx.strokeStyle = '#25ebd7'let x = 0let len = this.dataArray.length;let index = this.mWidth - len;for (let i = index + 1; i < this.mWidth; i++) {const mCenterY = this.mHeight / 2;const y = mCenterY - (this.dataArray[i - index - 1] / (32768 / mCenterY));// console.log(`i=${i},position=${i - index - 1},,data=${this.dataArray[i - index - 1]},,y=${y},,mCenterY=${mCenterY}`)x = i - 1;ctx.lineTo(x, y)ctx.stroke()}},}
}
</script>

相关文章:

  • (第30天)二叉树阶段总结
  • 更新pip版本(在自己工程中的虚拟环境中)
  • 再读高考作文题
  • 【CS.SE】Tomcat启动闪退问题解决方法
  • 「动态规划」打家劫舍的变形题,你会做吗?
  • 【Linux】动态库和静态库
  • 牛客NC18 顺时针旋转矩阵【中等 数学 Java/Go/PHP/C++】
  • 一款免费文件夹同步工具,旨在帮助用户在不同磁盘或文件夹间进行文件和目录的复制、移动和同步工作
  • C语言 树与二叉树基础部分
  • 关于Redis的持久化
  • 如何在 iPhone 上恢复已删除的短信
  • YOLOv10 超详细解析 | 网络结构、训练策略、论文解读
  • Linux第六章_实验案例:磁盘和文件系统管理(一)_实验案例:迁移/home分区
  • Golang发送邮件如何验证身份?有哪些限制?
  • Flink Rest Basic Auth - 安全认证
  • 【347天】每日项目总结系列085(2018.01.18)
  • C# 免费离线人脸识别 2.0 Demo
  • Git的一些常用操作
  • JavaScript 事件——“事件类型”中“HTML5事件”的注意要点
  • Just for fun——迅速写完快速排序
  • session共享问题解决方案
  • 彻底搞懂浏览器Event-loop
  • 前端学习笔记之观察者模式
  • 浅谈Kotlin实战篇之自定义View图片圆角简单应用(一)
  • 手写一个CommonJS打包工具(一)
  •  一套莫尔斯电报听写、翻译系统
  • Mac 上flink的安装与启动
  • 格斗健身潮牌24KiCK获近千万Pre-A轮融资,用户留存高达9个月 ...
  • ![CDATA[ ]] 是什么东东
  • #define、const、typedef的差别
  • #if 1...#endif
  • $ is not function   和JQUERY 命名 冲突的解说 Jquer问题 (
  • (rabbitmq的高级特性)消息可靠性
  • (附源码)apringboot计算机专业大学生就业指南 毕业设计061355
  • (四)JPA - JQPL 实现增删改查
  • (原創) 未来三学期想要修的课 (日記)
  • (自适应手机端)响应式新闻博客知识类pbootcms网站模板 自媒体运营博客网站源码下载
  • **Java有哪些悲观锁的实现_乐观锁、悲观锁、Redis分布式锁和Zookeeper分布式锁的实现以及流程原理...
  • .NET Core 成都线下面基会拉开序幕
  • .NET MAUI Sqlite程序应用-数据库配置(一)
  • .NET 中使用 TaskCompletionSource 作为线程同步互斥或异步操作的事件
  • .NET成年了,然后呢?
  • .net对接阿里云CSB服务
  • /var/spool/postfix/maildrop 下有大量文件
  • ::
  • @hook扩展分析
  • []C/C++读取串口接收到的数据程序
  • [acwing周赛复盘] 第 94 场周赛20230311
  • [C# 基础知识系列]专题十六:Linq介绍
  • [C++] vector list 等容器的迭代器失效问题
  • [CSS]中子元素在父元素中居中
  • [CTO札记]如何测试用户接受度?
  • [c语言]小课堂 day2
  • [INSTALL_FAILED_TEST_ONLY],Android开发出现应用未安装
  • [Kubernetes]8. K8s使用Helm部署mysql集群(主从数据库集群)