AudioListener - 表示音频场景中听众的位置和方向
AudioListener
接口表示聆听音频场景的唯一人员的位置和方向,并用于音频空间化。所有 PannerNode
相对于存储在 BaseAudioContext.listener
属性中的 AudioListener
进行空间化。
重要的是要注意,每个上下文只有一个听众,并且它不是 AudioNode
。
属性
position
、forward
和 up
值使用不同的语法设置和检索。例如,检索是通过访问 AudioListener.positionX
来完成的,而设置相同的属性是通过 AudioListener.positionX.value
来完成的。这就是为什么这些值未标记为只读的原因,这就是它们在规范的 IDL 中出现的方式。
AudioListener.positionX
表示听众在右手笛卡尔坐标系中的水平位置。默认值为 0。
AudioListener.positionY
表示听众在右手笛卡尔坐标系中的垂直位置。默认值为 0。
AudioListener.positionZ
表示听众在右手笛卡尔坐标系中的纵向(来回)位置。默认值为 0。
AudioListener.forwardX
表示与位置(positionX
,positionY
和 positionZ
)值相同的笛卡尔坐标系中听众的前进方向的水平位置。前向和向上值彼此线性独立。默认值为 0。
AudioListener.forwardY
表示与位置(positionX
,positionY
和 positionZ
)值相同的笛卡尔坐标系中听众的前进方向的垂直位置。前向和向上值彼此线性独立。默认值为 0。
AudioListener.forwardZ
表示与位置(positionX
,positionY
和 positionZ
)值相同的笛卡尔坐标系中听众的前进方向的纵向(来回)位置。前向和向上值彼此线性独立。默认值为 -1。
AudioListener.upX
表示与位置(positionX
,positionY
和 positionZ
)值相同的笛卡尔坐标系中听众头部的顶部的水平位置。前向和向上值彼此线性独立。默认值为 0。
AudioListener.upY
表示与位置(positionX
,positionY
和 positionZ
)值相同的笛卡尔坐标系中听众头部的顶部的垂直位置。前向和向上值彼此线性独立。预设值为 1。
AudioListener.upZ
表示与位置(positionX
,positionY
和 positionZ
)值相同的笛卡尔坐标系中听众头部顶部的纵向(来回)位置。前向和向上值彼此线性独立。默认值为 0。
方法
AudioListener.setOrientation()
设置听众的方向。
AudioListener.setPosition()
设置听众的位置。
注意:尽管不建议使用这些方法,但它们是当前在 Firefox,Internet Explorer 和 Safari 中设置方向和位置的唯一方法。
不推荐使用的功能
AudioListener.dopplerFactor
一个双精度值,表示渲染多普勒效果时要使用的音高偏移量。
AudioListener.speedOfSound
一个双精度值,表示声音的速度,以米/秒为单位。
在规范的先前版本中,可以使用 dopplerFactor
和 speedOfSound
属性以及 setPosition()
方法来控制应用于连接到下游的 AudioBufferSourceNode
的多普勒效果 - 这些将会根据 PannerNode
和 AudioListener
的相对速度上下倾斜。这些功能有很多问题:
- 仅
AudioBufferSourceNode
会上下调高,其他源节点不调高。 - 将
AudioBufferSourceNode
连接到多个PannerNode
时采取的行为尚不清楚。 - 因为声相调节器和听众的速度不是
AudioParam
,所以音调修改会导致音频失真。
由于这些问题,这些属性和方法已被删除。
setOrientation()
和 setPosition()
方法已通过设置其属性值等效项而被替换。例如,可以通过分别设置 positionX.value
,positionY.value
和 positionZ.value
来实现 setPosition(x, y, z)
。
The setOrientation()
and setPosition()
methods have been replaced by setting their property value equivilents.
实例
在下面的实例中,您将看到如何使用 createPanner()
方法、AudioListener
和 PannerNode
} 来控制音频空间化的示例。通常,您将在 3D 空间中定义音频监听器和声像器(源)最初占据的位置,然后在使用该应用程序时更新其中一个或两个的位置。例如,您可能要在游戏世界中移动角色,并希望随着您的角色靠近或远离音乐播放器(例如立体声音响)而使音频的传递发生实际变化。在实例中,您可以看到它是由 moveRight()
,moveLeft()
等函数控制的,它们通过 PositionPanner()
函数设置了全景位置的新值。
要查看完整的实现,请查看我们的 panner-node 实例(查看源代码)— 该演示将您带到 2.5D “金属房”,您可以在动臂箱上播放曲目,然后在动臂箱周围走动以查看声音如何变化!
请注意,我们如何使用某些功能检测为浏览器提供较新的属性值(例如 AudioListener.forwardX
)来设置位置(如果支持的话),或者使用较旧的方法(例如 AudioListener.setOrientation()
)(如果浏览器支持这些属性,但不支持新属性)。
// 设置监听器和声像器的位置信息
var WIDTH = window.innerWidth;
var HEIGHT = window.innerHeight;
var xPos = Math.floor(WIDTH/2);
var yPos = Math.floor(HEIGHT/2);
var zPos = 295;
// 定义其他变量
var AudioContext = window.AudioContext || window.webkitAudioContext;
var audioCtx = new AudioContext();
var panner = audioCtx.createPanner();
panner.panningModel = 'HRTF';
panner.distanceModel = 'inverse';
panner.refDistance = 1;
panner.maxDistance = 10000;
panner.rolloffFactor = 1;
panner.coneInnerAngle = 360;
panner.coneOuterAngle = 0;
panner.coneOuterGain = 0;
if(panner.orientationX) {
panner.orientationX.setValueAtTime(1, audioCtx.currentTime);
panner.orientationY.setValueAtTime(0, audioCtx.currentTime);
panner.orientationZ.setValueAtTime(0, audioCtx.currentTime);
} else {
panner.setOrientation(1,0,0);
}
var listener = audioCtx.listener;
if(listener.forwardX) {
listener.forwardX.setValueAtTime(0, audioCtx.currentTime);
listener.forwardY.setValueAtTime(0, audioCtx.currentTime);
listener.forwardZ.setValueAtTime(-1, audioCtx.currentTime);
listener.upX.setValueAtTime(0, audioCtx.currentTime);
listener.upY.setValueAtTime(1, audioCtx.currentTime);
listener.upZ.setValueAtTime(0, audioCtx.currentTime);
} else {
listener.setOrientation(0,0,-1,0,1,0);
}
var source;
var play = document.querySelector('.play');
var stop = document.querySelector('.stop');
var boomBox = document.querySelector('.boom-box');
var listenerData = document.querySelector('.listener-data');
var pannerData = document.querySelector('.panner-data');
leftBound = (-xPos) + 50;
rightBound = xPos - 50;
xIterator = WIDTH/150;
// 收听者将始终在此演示的同一位置
if(listener.positionX) {
listener.positionX.setValueAtTime(xPos, audioCtx.currentTime);
listener.positionY.setValueAtTime(yPos, audioCtx.currentTime);
listener.positionZ.setValueAtTime(300, audioCtx.currentTime);
} else {
listener.setPosition(xPos,yPos,300);
}
listenerData.innerHTML = '收听者数据:X ' + xPos + ' Y ' + yPos + ' Z ' + 300;
// 当音箱在屏幕上移动时,声像将移动
function positionPanner() {
if(panner.positionX) {
panner.positionX.setValueAtTime(xPos, audioCtx.currentTime);
panner.positionY.setValueAtTime(yPos, audioCtx.currentTime);
panner.positionZ.setValueAtTime(zPos, audioCtx.currentTime);
} else {
panner.setPosition(xPos,yPos,zPos);
}
pannerData.innerHTML = '声像数据:X ' + xPos + ' Y ' + yPos + ' Z ' + zPos;
}
注意:在确定要应用于监听器和声像器的位置值,使声音适合屏幕上的视觉效果方面,需要进行大量的数学运算,但是通过一些实验,您很快就会习惯了。
规范
规范 | 状态 | 备注 |
---|---|---|
Web Audio API AudioListener 的定义 |
工作草案 | - |
桌面浏览器兼容性
特性 | Chrome | Edge | Firefox | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|---|
基础支持 | 14 | ≤18 | 25 | 不支持 | 15 | 6 |
dopplerFactor | 14 — 56 | 12 — 79 | 25 — 63 | 不支持 | 15 — 43 | 6 |
forwardX | 52 | ≤18 | 不支持1 | 不支持 | 39 | 不支持 |
forwardY | 52 | ≤18 | 不支持1 | 不支持 | 39 | 不支持 |
forwardZ | 52 | ≤18 | 不支持1 | 不支持 | 39 | 不支持 |
positionX | 52 | ≤18 | 不支持1 | 不支持 | 39 | 不支持 |
positionY | 52 | ≤18 | 不支持1 | 不支持 | 39 | 不支持 |
positionZ | 52 | ≤18 | 不支持1 | 不支持 | 39 | 不支持 |
setOrientation | 14 | 18 | 25 | 不支持 | 15 | 6 |
setPosition | 14 | 12 | 25 | 不支持 | 15 | 6 |
speedOfSound | 14 — 56 | 12 — 79 | 25 — 63 | 不支持 | 15 — 43 | 6 |
upX | 52 | ≤18 | 不支持1 | 不支持 | 39 | 不支持 |
upY | 52 | ≤18 | 不支持1 | 不支持 | 39 | 不支持 |
upZ | 52 | ≤18 | 不支持1 | 不支持 | 39 | 不支持 |
移动浏览器兼容性
特性 | Android | Chrome for Android | Edge mobile | Firefox for Android | IE mobile | Opera Android | iOS Safari |
---|---|---|---|---|---|---|---|
基础支持 | 支持 | 18 | 未知 | 26 | 未知 | 14 | 支持 |
dopplerFactor | 支持 — 56 | 18 — 56 | 未知 | 26 — 63 | 未知 | 14 — 43 | 未知 |
forwardX | 52 | 52 | 未知 | 不支持1 | 未知 | 41 | 未知 |
forwardY | 52 | 52 | 未知 | 不支持1 | 未知 | 41 | 未知 |
forwardZ | 52 | 52 | 未知 | 不支持1 | 未知 | 41 | 未知 |
positionX | 52 | 52 | 未知 | 不支持1 | 未知 | 41 | 未知 |
positionY | 52 | 52 | 未知 | 不支持1 | 未知 | 41 | 未知 |
positionZ | 52 | 52 | 未知 | 不支持1 | 未知 | 41 | 未知 |
setOrientation | 支持 | 18 | 未知 | 26 | 未知 | 14 | 支持 |
setPosition | 支持 | 18 | 未知 | 26 | 未知 | 14 | 支持 |
speedOfSound | 支持 — 56 | 18 — 56 | 未知 | 26 — 63 | 未知 | 14 — 43 | 未知 |
upX | 52 | 52 | 未知 | 不支持1 | 未知 | 41 | 未知 |
upY | 52 | 52 | 未知 | 不支持1 | 未知 | 41 | 未知 |
upZ | 52 | 52 | 未知 | 不支持1 | 未知 | 41 | 未知 |
1. 支持废弃的设置方向的方法 - setOrientation()
方法。