正文
-
创建音频上下文
-
创建并初始化输入结点、处理结点
-
将输入结点、处理结点、输出结点进行有连接
-
动态修改结点属性以输出不同音效
参考以下代码:
const myAudio = document.querySelector('audio');
const audioCtx = new AudioContext(); // 创建音频上下文
// 创建输入结点,解码audio标签的音频源;创建处理结点,处理音频
const source = audioCtx.createMediaElementSource(myAudio);
const gainNode = audioCtx.createGain(); // 创建GainNode结点控制音频振幅
// 将输入结点、处理结点、输出结点两两相连
source.connect(gainNode); // 将输入结点连接到gainNode处理结点
gainNode.connect(audioCtx.destination); // 将gainNode连接到destination输出节点
// 通过动态改变结点属性产生不同音效
source.start(0); // 播放音频
gainNode.gain.value = val; // 设置音量
理解了Web Audio的开发流程,接下来看看如何在WebVR中实现Audio Spatialization,这里VR场景使用three.js进行开发。
实现空间化音频
Audio Spatialization的实现主要通过
AudioListener
和
PannerNode
结点配合,这两个对象可以根据空间方位信息动态处理音频源,并输出左右声道。
-
AudioListener
对象代表三维空间中的听者(用户),通过
AudioContext.listener
属性获取;
-
PannerNode
对象指的是三维空间中的发声体,通过
AudioContext.createPanner()
创建。
我们需要初始化这两个对象,并将空间方位信息作为入参动态传给它们。
设置PannerNode
const myAudio = document.querySelector('audio');
const audioCtx = new AudioContext(); // 创建音频上下文
const source = audioCtx.createMediaElementSource(myAudio);
// 设置PannerNode位置
const panner = audioCtx.createPannerNode();
panner.setPosition(speaker.position.x, speaker.position.y, speaker.position.z); // 将发声体坐标传给PannerNode
source.connect(panner); // 将输入结点连接到PannerNode处理结点
panner.connect(audioCtx.destination); // PannerNode连接至输出结点
source.start(0); // 播放音频
设置AudioListener
VR用户头显最多有6-Dof:position位置3-Dof系统和orientation方向3-Dof系统,我们需要将这6-Dof的信息传入AudioListener,由它为我们处理音频数据。
对于用户位置数据,AudioListener提供了三个位置属性:
positionX
,
positionY
,
positionZ
,它分别代表听者当前位置的xyz坐标,我们可将用户在场景中的位置(一般用camera的position)赋值给这三个属性。
// 为listener设置position
const listener = audioCtx.listener;
listener.positionX = camera.position.x;
listener.positionY = camera.position.y;
listener.positionZ = camera.position.z;
除了传入用户的位置,我们还需要将用户的视角方向信息传给
AudioListener
,具体是给AudioListener的Forward向量三个分量
forwardX
,
forwardY
,
forwardZ
和Up向量三个分量
upX
,
upY
,
upZ
赋值。