Canvas实现音频可视化波形图

1. 效果演示

  • 上图演示了音频的波形随着音乐的节奏而跌宕起伏

2. 基本概念说明

2.1 音频源节点

  • 音频数据的来源,是音频处理的其中一个环节

2.2 时域图

  • 声音信号是一维的时域信号,无法观察出频率随时间的变化规律
  • 横轴代表时间, 纵轴是信号的变化(振幅)

2.3 频谱图

  • 任何信号(当然要满足一定的数学条件),都可以通过傅立叶变换而分解成一个直流分量(也就是一个常数)和若干个(一般是无穷多个)正弦信号的和
  • 每个正弦分量都有自己的频率和幅值,频率值作横轴,幅值作纵轴

3. 案例代码

html 复制代码
<!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>Canvas在音频可视化的应用</title>
  </head>
  <body>
    <canvas></canvas>
    <audio src="./1.mp3" controls></audio>
    <script>
      const audio = document.querySelector('audio')
      const canvas = document.querySelector('canvas')
      const con = canvas.getContext('2d')

      // 初始化canvas的尺寸
      canvas.width = window.innerWidth // 窗口的内部宽度
      canvas.height = window.innerHeight / 2 //窗口的内部高度
      document.body.style.backgroundColor = '#000000' // 背景颜色设置为黑色

	  // 定义数组和音频分析器
      let dataArray, analyser
      audio.onplay = () => {
        // 初始化
        const audCon = new AudioContext() // 创建音频上下文
        const source = audCon.createMediaElementSource(audio) // 创建音频源节点
        // 创建音频分析器
        analyser = audCon.createAnalyser()
        // 快速傅里叶变换的长度必须为2的整数幂
        analyser.fftSize = 512 // 这里把快速傅里叶变换的长度设置为512
        // 连接音频源节点到音频分析器上
        source.connect(analyser)
        // 连接音频分析器到音频终端上
        analyser.connect(audCon.destination)
        // 创建数组,用于接收分析器节点的分析数据
        // Uint8Array 数组类型表示一个 8 位无符号整型数组
        // frequencyBinCount是fftSize值的一半作为可视化音频的数组长度
        dataArray = new Uint8Array(analyser.frequencyBinCount)
      }

      // 把分析出的波形绘制到canvas上
      (function draw() {
        // 动画帧,按帧绘制canvas
        requestAnimationFrame(draw)
        // 清空画布
        const { width, height } = canvas
        con.clearRect(0, 0, width, height)
        // 让分析器节点分析出数据到数组中
        analyser.getByteFrequencyData(dataArray)
        // 设置canvas上下文绘制的颜色
        con.fillStyle = 'skyblue'
        // len表示获取分析到的音频数据数组长度的
        // 这里除以2.5是剔除不经常出现的高频的部分
        const len = dataArray.length / 2.5
        // barWidth表示每个波形矩形的宽度
        // 这里除以2是为了绘制对称的波形图
        const barWidth = width / len / 2
        for (let i = 0; i < len; i++) {
		  // data是8位数组的每个数据,因为是一个字节,即data的值都是 <= 255
          const data = dataArray[i] 
          // barHeight表示每个波形矩形的高度,值为单位长度乘canvas容器的高
          const barHeight = (data / 255) * height
          // 绘制点y
          const y = height - barHeight
          // 绘制点x1
          const x1 = i * barWidth + width / 2
          // 绘制点x2
          const x2 = width / 2 - (i + 1) * barWidth
          // 绘制右半部分波形图
          con.fillRect(x1, y, barWidth - 2, barHeight)
          // 绘制左半部分波形图
          con.fillRect(x2, y, barWidth - 2, barHeight)
        }
      })()
    </script>
  </body>
</html>
相关推荐
yuehua_zhang16 分钟前
uni app 的app端 写入运行日志到指定文件夹。
前端·javascript·uni-app
IT_陈寒1 小时前
SpringBoot 3.x实战:5种高并发场景下的性能优化秘籍,让你的应用快如闪电!
前端·人工智能·后端
麦文豪(victor)1 小时前
自动化流水线
前端
JarvanMo2 小时前
Flutter. FractionallySizedBox
前端
知识分享小能手3 小时前
React学习教程,从入门到精通, React 入门指南:React JSX 语法知识点详解及案例代码(8)
前端·javascript·vue.js·学习·react.js·前端框架·anti-design-vue
卓码软件测评3 小时前
第三方web测评机构:【WEB安全测试中HTTP方法(GET/POST/PUT)的安全风险检测】
前端·网络协议·安全·web安全·http·xss
学习3人组3 小时前
React 组件基础与事件处理
前端·javascript·react.js
漂流瓶jz9 小时前
解锁Babel核心功能:从转义语法到插件开发
前端·javascript·typescript
周小码9 小时前
shadcn-table:构建高性能服务端表格的终极解决方案 | 2025最新实践
前端·react.js
大怪v9 小时前
老乡,别走!Javascript隐藏功能你知道吗?
前端·javascript·代码规范