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>
相关推荐
用户54330814419413 小时前
AI 时代,前端逆向的门槛已经低到离谱 — 以 Upwork 为例
前端
JarvanMo13 小时前
Flutter 版本的 material_ui 已经上架 pub.dev 啦!快来抢先体验吧。
前端
恋猫de小郭14 小时前
AI 可以让 WIFI 实现监控室内人体位置和姿态,无需摄像头?
前端·人工智能·ai编程
哀木14 小时前
给自己整一个 claude code,解锁编程新姿势
前端
程序员鱼皮14 小时前
GitHub 关注突破 2w,我总结了 10 个涨星涨粉技巧!
前端·后端·github
UrbanJazzerati14 小时前
Vue3 父子组件通信完全指南
前端·面试
是一碗螺丝粉14 小时前
5分钟上手LangChain.js:用DeepSeek给你的App加上AI能力
前端·人工智能·langchain
wuhen_n14 小时前
双端 Diff 算法详解
前端·javascript·vue.js
UrbanJazzerati14 小时前
Vue 3 纯小白快速入门指南
前端·面试
雮尘14 小时前
手把手带你玩转Android gRPC:一篇搞定原理、配置与客户端开发
android·前端·grpc