THREE.AudioListener
是 Three.js 中用于监听音频的类。它可以附加到摄像机或场景,并接收 PositionalAudio
或 Audio
实例的音频输出,并将其渲染到声音设备。
入参(Parameters)
- 无
出参(Return Values)
- 无
方法(Methods)
-
setPosition(x, y, z)
:- 描述:设置监听器的位置。
- 参数:
x
(Number):X 轴坐标。y
(Number):Y 轴坐标。z
(Number):Z 轴坐标。
- 返回值:无
-
setOrientation(x, y, z, xUp, yUp, zUp)
:- 描述:设置监听器的方向。
- 参数:
x
(Number):前方方向的 X 轴分量。y
(Number):前方方向的 Y 轴分量。z
(Number):前方方向的 Z 轴分量。xUp
(Number):上方方向的 X 轴分量。yUp
(Number):上方方向的 Y 轴分量。zUp
(Number):上方方向的 Z 轴分量。
- 返回值:无
-
setMasterVolume(value)
:- 描述:设置主音量。
- 参数:
value
(Number):主音量的值,范围从 0(静音)到 1(最大音量)。
- 返回值:无
-
getMasterVolume()
:- 描述:获取主音量。
- 参数:无
- 返回值:主音量的值。
属性(Properties)
type
(String):表示对象类型的字符串,值为'AudioListener'
。context
(AudioContext):表示音频上下文的AudioContext
实例。gain
(GainNode):表示音频增益的GainNode
实例。filter
(BiquadFilterNode):表示音频过滤器的BiquadFilterNode
实例。timeDelta
(Number):上次更新到现在的时间差,单位为秒。position
(THREE.Vector3):监听器的位置。up
(THREE.Vector3):监听器的上方向。forward
(THREE.Vector3):监听器的前方方向。
PositionalAudioHelper
是 Three.js 中用于帮助可定位音频的辅助类。它用于可视化 PositionalAudio
的方向和范围,并提供一些方法和属性来管理和操作音频的位置和状态。
出参(Return Values)
- 无
入参(Parameters)
audio
(THREE.PositionalAudio): 要关联的PositionalAudio
实例。
方法(Methods)
update()
:- 描述:更新音频辅助器的位置和方向。
- 参数:无
- 返回值:无
属性(Properties)
audio
(THREE.PositionalAudio):与辅助器相关联的PositionalAudio
实例。isPositionalAudioHelper
(Boolean):表示对象是否为PositionalAudioHelper
的实例。matrix
(THREE.Matrix4):音频辅助器的变换矩阵。matrixAutoUpdate
(Boolean):指示音频辅助器是否自动更新变换矩阵。material
(THREE.LineBasicMaterial):音频辅助器的材质。geometry
(THREE.BufferGeometry):音频辅助器的几何体。type
(String):音频辅助器的类型,默认为'LineSegments'
。color
(THREE.Color):音频辅助器的颜色。directionalLength
(Number):指示音频辅助器中表示方向的线段的长度。coneLength
(Number):指示音频辅助器中表示范围的圆锥的长度。coneWidth
(Number):指示音频辅助器中表示范围的圆锥的宽度。coneColor
(THREE.Color):音频辅助器中表示范围的圆锥的颜色。decibels
(Number):音频辅助器中表示范围的圆锥的声音强度(分贝)。maxRange
(Number):音频辅助器的最大范围。
这些属性和方法可用于控制和调整 PositionalAudioHelper
的行为和外观,以便更好地调试和管理定位音频的效果。
demo 源码
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webaudio - orientation</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<audio loop id="music" preload="auto" style="display: none">
<source src="sounds/376737_Skullbeatz___Bad_Cat_Maste.ogg" type="audio/ogg">
<source src="sounds/376737_Skullbeatz___Bad_Cat_Maste.mp3" type="audio/mpeg">
</audio>
<div id="overlay">
<button id="startButton">Play</button>
</div>
<div id="container"></div>
<div id="info">
<a href="https://threejs.org" target="_blank" rel="noopener noreferrer">three.js</a> webaudio - orientation<br/>
music by <a href="http://www.newgrounds.com/audio/listen/376737" target="_blank" rel="noopener noreferrer">skullbeatz</a>
</div>
<script type="importmap">
{
"imports": {
"three": "../build/three.module.js",
"three/addons/": "./jsm/"
}
}
</script>
<script type="module">
// 导入所需的模块
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { PositionalAudioHelper } from 'three/addons/helpers/PositionalAudioHelper.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
let scene, camera, renderer;
const startButton = document.getElementById('startButton');
startButton.addEventListener('click', init);
function init() {
const overlay = document.getElementById('overlay');
overlay.remove();
const container = document.getElementById('container');
// 创建相机
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 100);
camera.position.set(3, 2, 3);
// 加载立方体贴图
const reflectionCube = new THREE.CubeTextureLoader()
.setPath('textures/cube/SwedishRoyalCastle/')
.load(['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg']);
// 创建场景并设置背景和雾效
scene = new THREE.Scene();
scene.background = new THREE.Color(0xa0a0a0);
scene.fog = new THREE.Fog(0xa0a0a0, 2, 20);
// 创建半球光和方向光
const hemiLight = new THREE.HemisphereLight(0xffffff, 0x8d8d8d, 3);
hemiLight.position.set(0, 20, 0);
scene.add(hemiLight);
const dirLight = new THREE.DirectionalLight(0xffffff, 3);
dirLight.position.set(5, 5, 0);
dirLight.castShadow = true;
dirLight.shadow.camera.top = 1;
dirLight.shadow.camera.bottom = -1;
dirLight.shadow.camera.left = -1;
dirLight.shadow.camera.right = 1;
dirLight.shadow.camera.near = 0.1;
dirLight.shadow.camera.far = 20;
scene.add(dirLight);
// 创建地面和网格
const mesh = new THREE.Mesh(new THREE.PlaneGeometry(50, 50), new THREE.MeshPhongMaterial({ color: 0xcbcbcb, depthWrite: false }));
mesh.rotation.x = -Math.PI / 2;
mesh.receiveShadow = true;
scene.add(mesh);
const grid = new THREE.GridHelper(50, 50, 0xc1c1c1, 0xc1c1c1);
scene.add(grid);
// 创建监听器和定位音频
const listener = new THREE.AudioListener();
camera.add(listener);
const audioElement = document.getElementById('music');
audioElement.play();
const positionalAudio = new THREE.PositionalAudio(listener);
positionalAudio.setMediaElementSource(audioElement);
positionalAudio.setRefDistance(1);
positionalAudio.setDirectionalCone(180, 230, 0.1);
const helper = new PositionalAudioHelper(positionalAudio, 0.1);
positionalAudio.add(helper);
// 加载 glTF 模型
const gltfLoader = new GLTFLoader();
gltfLoader.load('models/gltf/BoomBox.glb', function (gltf) {
const boomBox = gltf.scene;
boomBox.position.set(0, 0.2, 0);
boomBox.scale.set(20, 20, 20);
boomBox.traverse(function (object) {
if (object.isMesh) {
object.material.envMap = reflectionCube;
object.geometry.rotateY(-Math.PI);
object.castShadow = true;
}
});
boomBox.add(positionalAudio);
scene.add(boomBox);
animate();
});
// 创建一个遮挡声音的墙体
const wallGeometry = new THREE.BoxGeometry(2, 1, 0.1);
const wallMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000,
transparent: true, opacity: 0.5 });
const wall = new THREE.Mesh(wallGeometry, wallMaterial);
wall.position.set(0, 0.5, -0.5);
scene.add(wall);
// 创建渲染器
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
// 创建控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(0, 0.1, 0);
controls.update();
controls.minDistance = 0.5;
controls.maxDistance = 10;
controls.maxPolarAngle = 0.5 * Math.PI;
// 监听窗口大小变化
window.addEventListener('resize', onWindowResize);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
</script>
</body>
</html>
s