web audio api 实现音频的可视化

打算做一个带有音频波形显示的音乐播放器,因此去学习了web audio api的使用,个人认为web audio api是H5的audio标签的扩展,在此基础上添加了对音频的各种处理,例如实现高精度的音频计算,音频混响器,3D音频,与audio/ WebRTC的集成。本文仅是我的学习记录,有错误可指出。

使用web audio api的基本流程

1.创建一个AudioContext对象。
2.给AudioContext对象添加声音源,声音源可以是

1.创建一个AudioContext对象

AudioContext是web audio api的第一步也是最不可或缺的,类似于canvas的getContext

const AudioContext = window.AudioContext || window.webkitAudioContext;
this.audioContext = new AudioContext();
2.创建AnalyserNode获取音频频率数据
this.analyser = this.audioContext.createAnalyser();
this.analyser.fftSize = 256; //设置傅里叶系数
3.给AudioContext对象添加声音源并连接
const xhr = new XMLHttpRequest();
      xhr.open("GET", this.currentMusicDetail.songLink, true);
      // 设置响应类型为 arraybuffer
      xhr.responseType = "arraybuffer";
      const that = this;
      xhr.onload = function () {
        that.source = that.audioContext.createBufferSource();
        // 对响应内容进行解码
        that.audioContext.decodeAudioData(xhr.response, function (buffer) {
          // 将解码后得到的值赋给buffer
          that.source.buffer = buffer;
          // 音频==》分析器==》扬声器
          that.source.connect(that.analyser);
          that.analyser.connect(that.audioContext.destination);
        });
      };
      xhr.send();

当我在添加音频源的时候遇到了两个问题
第一,本来打算使用MediaElementAudioSourceNode 将

4.绘制音频柱形图
getCanvas() {
      //创建canvas对象
      const canvas = document.getElementById("canvas");
      const cxt = canvas.getContext("2d");
      const WIDTH = canvas.width;
      const HEIGHT = canvas.height;
      const lineWidth = 4;
      const gap = 6;
      const maxNum = Math.round(WIDTH / (lineWidth + gap));
      cxt.strokeStyle = "red";
      cxt.lineCap = "round";
      cxt.lineWidth = lineWidth;
      const that = this;
      function render() {
        cxt.clearRect(0, 0, WIDTH, HEIGHT); //清空画布
        //that.analyser.frequencyBinCount是fftSize的一半
        const dataArray = new Uint8Array(that.analyser.frequencyBinCount);
        that.analyser.getByteFrequencyData(dataArray); //获取音频字节流
        for (let i = 0; i < maxNum; i++) {
          cxt.strokeStyle = "#008b8b";
          const value = Math.round((dataArray[i] / 128) * 20);
          cxt.beginPath();
          cxt.moveTo(i * (lineWidth + gap) + gap / 2, HEIGHT / 2);
          cxt.lineTo(i * (lineWidth + gap) + gap / 2, HEIGHT / 2 - value - 2);
          cxt.stroke();
          cxt.beginPath();
          cxt.moveTo(i * (lineWidth + gap) + gap / 2, HEIGHT / 2);
          cxt.lineTo(i * (lineWidth + gap) + gap / 2, HEIGHT / 2 + value + 2);
          cxt.stroke();
        }
        window.requestAnimationFrame(render); //递归调用渲染
      }
      // requestAnimationFrame()用来渲染动画帧,此时渲染第一帧
      window.requestAnimationFrame(render);
    }
4.音频的播放,暂停

在音频的播放方面,个人认为会使用 AudioBufferSourceNode比使用audio节点复杂的多,这里主要用到了接口

  1. AudioBufferSourceNode.start(when,offset,duration)
    when: 表示从何时开始播放,默认为0,表示立即播放,这里与 AudioContext使用相同的时间坐标系统
    offset: 偏移值
    duration: 音频的持续时间
  2. AudioBufferSourceNode.stop(when)
    when: 结束时间
  3. AudioContext.currentTime 获取当前音频播放时间
	//音频的播放
	play() {
      that.startTime = that.audioContext.currentTime;
      that.source.start(0, that.offset);
	}
	//音频的暂停
    pause() {
      if (!this.currentMusicDetail || !this.source) return;
      this.source.stop(0);
      this.source.disconnect(0);
      this.source = null;
      this.offset = this.getPosition();
      this.startTime = null;
    },
    //音频的停止
    stop() {
      this.pause();
      this.offset = 0;
    },
    //获得暂停的位置
    getPosition() {
      return (
        this.offset +
        (this.startTime !== null
          ? this.audioContext.currentTime - this.startTime
          : 0)
      );
    },

学习下来发现对web audio api虽然有了初步的认识,但具体还是不太明白,由于web audio api 的功能非常强大,等我有时间我还会去研究的。

你可能感兴趣的:(web,audio,api,vue,canvas)