【前端】Web Audio API接口介绍

简言

记录下Web Audio API接口的介绍。
Web Audio API 提供了在 Web 上控制音频的一个非常有效通用的系统,允许开发者来自选音频源,对音频添加特效,使音频可视化,添加空间效果(如平移),等等。

Web Audio API

Web Audio API 使用户可以在音频上下文(AudioContext)中进行音频操作。
基本音频操作通过音频节点执行,这些节点连接在一起形成音频路由图。即使在单个上下文中,也可支持多个具有不同类型通道布局的音源。这种模块化设计为创建具有动态效果的复杂音频功能提供了灵活性。这种模块化设计提供了灵活创建动态效果的复合音频的方法。

音频节点(audio node)通过它们的输入输出相互连接,形成一个链或者一个简单的网。一般来说,这个链或网起始于一个或多个音频源。
音频源可以提供一个片段一个片段的音频采样数据(以数组的方式),也可以是音频或视频的文件读出来的,又或者是音频流(MediaStreamAudioSourceNode)。

这些节点的输出可以连接到其他节点的输入上,然后新节点可以对接收到的采样数据再进行其他的处理,再形成一个结果流。

声音处理完成之后,可以连接到一个目的地(AudioContext.destination),这个目的地负责把声音数据传输给扬声器或者耳机。注意,只有当用户期望听到声音时,才需要进行最后一个这个连接。

web audio流程如下:

  1. 使用 AudioContext 创建音频上下文。
  2. 在音频上下文里创建音频源,音频源可以是上面说的那三种情况。
  3. 对音频进行处理(当然也可以不处理),处理需要创建效果节点,例如混响、双二阶滤波器、平移、压缩等。
  4. 为音频选择一个目的地,例如你的系统扬声器
  5. 连接源到效果器,对目的地进行效果输出。

Web Audio API 接口

Web Audio API 共有一系列接口和相关的事件。

  • AudioContext — AudioContext 接口代表由音频模块构成的音频处理图。音频上下文控制其所包含节点的创建和音频处理、解码。使用其他接口前你必需创建一个音频上下文,一切操作都在这个环境里进行。
  • AudioNode — 音频节点 接口是一个音频处理模块,包含了音频源节点、音频输出、音量控制节点等。
  • AudioParam — AudioParam 接口代表音频相关的参数,比如一个 AudioNode的参数。它可以设置为特定值或值的变化,并且可以在指定的时间之后以指定模式变更。
  • ended结束事件 — 当媒体播放停止时,会触发ended事件。
  • OscillatorNode — OscillatorNode 接口代表一种随时间变化的波形,比如正弦波形或三角波形。类型是AudioNode,功能是音频处理模块,可以产生指定频率的波形。
  • AudioBuffer — AudioBuffer 代表内存中的一段音频数据,可以通过AudioContext.decodeAudioData()方法从音频文件创建,也可以通过AudioContext.createBuffer()方法从原始数据创建。当音频数据被解码成这种格式之后,就可以被放入一个AudioBufferSourceNode中使用。
  • AudioBufferSourceNode — AudioBufferSourceNode 表示由内存音频数据组成的音频源,音频数据存储在AudioBuffer中。这是一个作为音频源的AudioNode。
  • MediaElementAudioSourceNode — MediaElementAudioSourceNode 接口表示由 HTML5 <audio>或<video>元素生成的音频源。这是一个作为音频源的AudioNode。
  • MediaStreamAudioSourceNode — MediaStreamAudioSourceNode 接口表示由 WebRTC MediaStream(如网络摄像头或麦克风)生成的音频源。这是一个作为音频源的AudioNode。
  • BiquadFilterNode — BiquadFilterNode 接口表示一个简单的低阶滤波器。它是一个AudioNode,可以表示不同种类的滤波器、调音器或图形均衡器。BiquadFilterNode 总是只有一个输入和一个输出。
  • ConvolverNode — ConvolverNode 接口是一个AudioNode,对给定的 AudioBuffer 执行线性卷积,通常用于实现混响效果。
  • DelayNode — DelayNode 接口表示延迟线;是AudioNode 类型的音频处理模块,使输入的数据延时输出。
  • DynamicsCompressorNode — DynamicsCompressorNode 提供了一个压缩效果,当多个音频在同时播放并且混合的时候,可以通过它降低音量最大的部分的音量来帮助避免发生削波和失真。
  • GainNode — GainNode 接口用于音量变化。它是一个 AudioNode 类型的音频处理模块,输入后应用增益 效果,然后输出。
  • StereoPannerNode — StereoPannerNode 接口表示一个简单立体声控制节点,用来左右移动音频流(左右声道处理)。
  • WaveShaperNode — WaveShaperNode 接口表示一个非线性的扭曲。它是AudioNode类型,可以利用曲线来对信号进行扭曲。除了一些效果明显的扭曲,还常被用来给声音添加温暖的感觉(暖调处理)。
  • PeriodicWave — 用来定义周期性的波形,可被用来重塑 OscillatorNode的输出。
  • AudioDestinationNode — AudioDestinationNode 定义了最后音频要输出到哪里,通常是输出到你的扬声器。
  • MediaStreamAudioDestinationNode — MediaStreamAudioDestinationNode 定义了使用 WebRTC 的MediaStream(只包含单个 AudioMediaStreamTrack)应该连接的目的地,AudioMediaStreamTrack 的使用方式和从getUserMedia()中得到MediaStream相似。这个接口是AudioNode类型的音频目的地。
  • AnalyserNode — AnalyserNode 表示一个可以提供实时频率分析与时域分析的切点,这些分析数据可以用做数据分析和可视化。如果你想从音频里提取时间、频率或者其他数据,你需要 AnalyserNode
  • ChannelSplitterNode — ChannelSplitterNode 可以把输入流的每个声道输出到一个独立的输出流(通道分离)。
  • ChannelMergerNode — ChannelMergerNode 用于把一组输入流合成到一个输出流。输出流的每一个声道对应一个输入流(通道合并)。
  • AudioListener — 代表场景中正在听声音的人的位置和朝向。
  • PannerNode — PannerNode 用于表示场景是声音的空间行为。它是AudioNode类型的音频处理模块,这个节点用于表示右手笛卡尔坐标系里声源的位置信息,运动信息(通过一个速度向量表示),方向信息(通过一个方向圆锥表示)。
  • ScriptProcessorNode — ScriptProcessorNode 接口用于通过 JavaScript 代码生成,处理,分析音频。它是一个AudioNode类型的音频处理模块,但是它与两个缓冲区相连接,一个缓冲区里包含当前的输入数据,另一个缓冲区里包含着输出数据。每当新的音频数据被放入输入缓冲区,就会产生一个AudioProcessingEvent 事件,当这个事件处理结束时,输出缓冲区里应该写好了新数据。
  • audioprocess事件 — 当一个 Web Audio API ScriptProcessorNode已经准备好进行处理时,这个事件回调会被调用。
  • AudioProcessingEvent 事件 — 当ScriptProcessorNode的输入流数据准备好了时,AudioProcessingEvent事件会产生。
  • OfflineAudioContext — OfflineAudioContext 离线音频上下文也是音频上下文AudioContext,也表示把AudioNode连接到一起的一个音频处理图。但是,与一个标准的音频上下文相比,离线上下文不能把音频渲染到扬声器,仅仅是把音频渲染到一个缓冲区。
  • complete — Complete 事件,当离线音频上下文被终止时产生。
  • OfflineAudioCompletionEvent 事件 — OfflineAudioCompletionEvent表示上下文被终止时的事件。

示例

音频可视化:

<!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>可视化</title>
  <style>
    #canvas,
    #canvas2 {
      border: 1px solid #000;
    }
  </style>
</head>
<h1>声音可视化</h1>
<div>
  <audio controls autoplay loop crossorigin="anonymous">
    <source src="./2789078374.mp3" type="audio/mpeg">
    Your browser does not support the audio element.
  </audio>

  <h2>可视化图形</h2>
  <canvas id="canvas"></canvas>
  <canvas id="canvas2"></canvas>

  <button id="btn">生成</button>
</div>

<body>
  <script>
    const canvasDom = document.getElementById("canvas");
    const canvasW = 1000
    const canvasH = 256
    canvasDom.width = canvasW;
    canvasDom.height = canvasH;
    const canvasCtx = canvasDom.getContext("2d");
    const canvasDom2 = document.getElementById("canvas2");

    canvasDom2.width = canvasW;
    canvasDom2.height = canvasH;
    const canvasCtx2 = canvasDom2.getContext("2d");
    const btn = document.getElementById("btn");
    let audioCtx = null
    let analyser
    let source
    btn.addEventListener("click", () => {

      if (audioCtx == null) {
        audioCtx = new (window.AudioContext || window.webkitAudioContext)()
        //  创建 AnalyserNode节点 
        analyser = audioCtx.createAnalyser()
        const distortion = audioCtx.createWaveShaper()
        //  连接声源 
        source = audioCtx.createMediaElementSource(document.querySelector('audio'))
        source.connect(analyser)
        analyser.connect(audioCtx.destination);
      }

      analyser.fftSize = 2048
      let bufferLength = analyser.frequencyBinCount
      const dataArray = new Uint8Array(bufferLength)
      analyser.getByteTimeDomainData(dataArray)

      //要捕获数据,你需要使用 AnalyserNode.getFloatFrequencyData() 或 AnalyserNode.getByteFrequencyData() 方法来获取频率数据,
      // 用 AnalyserNode.getByteTimeDomainData() 或 AnalyserNode.getFloatTimeDomainData() (en-US) 来获取波形数据。




      let drawVisual;
      canvasCtx.clearRect(0, 0, canvasW, canvasH);
      //  波形图
      function draw() {
        analyser.getByteTimeDomainData(dataArray)
        canvasCtx.fillStyle = "rgb(200, 200, 200)";
        canvasCtx.fillRect(0, 0, canvasW, canvasH);
        var sliceWidth = (canvasW * 1.0) / bufferLength;

        canvasCtx.lineWidth = 2;
        canvasCtx.strokeStyle = "rgb(0, 0, 0)";
        canvasCtx.beginPath();
        canvasCtx.moveTo(0, canvasH / 2);

        canvasCtx.lineTo(canvasW, canvasH / 2);
        canvasCtx.stroke()
        canvasCtx.beginPath();

        let x = 0
        for (let i = 0; i < bufferLength; i++) {
          let v = dataArray[i] / 128.0;
          let y = (v * canvasH) / 2;

          if (i === 0) {
            canvasCtx.moveTo(x, y);
          } else {

            canvasCtx.lineTo(x, y);
          }

          x += sliceWidth;

          canvasCtx.stroke();
        }
        drawVisual = requestAnimationFrame(draw);
      }
      draw()
      //  柱形图
      function drawBar() {
        analyser.getByteTimeDomainData(dataArray)
        canvasCtx2.fillStyle = "rgb(0,0,0)";
        canvasCtx2.fillRect(0, 0, canvasW, canvasH);
        let barWidth = canvasW / bufferLength * 2.5;
        let x = 0
        for (let i = 0; i < bufferLength; i++) {
          let barHeight = dataArray[i] / 128.0 / 2 * canvasH;
          canvasCtx2.fillStyle = 'rgb(' + (barHeight + 100) + ',50,50)';
          canvasCtx2.fillRect(x, canvasH - barHeight, barWidth, barHeight);

          x += barWidth + 1;
        }
        requestAnimationFrame(drawBar);
      }
      drawBar()
    })


  </script>
</body>

</html>

使用 file://打开的话会报cors,使用http服务打开。

在这里插入图片描述
在这里插入图片描述

结语

结束了。

  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZSK6

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值