THREE.AudioAnalyser
是 Three.js 中用于音频分析的类。它允许开发人员对音频进行频谱分析,并提供了一些方法和属性来获取音频的频域数据和时域数据。
入参(Parameters)
audio
(Audio
或PositionalAudio
):要分析的音频实例,可以是普通的Audio
或位置音频PositionalAudio
。
出参(Return Values)
- 无
方法(Methods)
-
`getFrequencyData():
- 描述:获取音频的频域数据。
- 参数:无
- 返回值:表示音频频域数据的数组。
-
getAverageFrequency()
:- 描述:获取音频的平均频率。
- 参数:无
- 返回值:表示音频平均频率的数字。
-
getFrequencyBinCount()
:- 描述:获取音频频域数据的数量。
- 参数:无
- 返回值:表示音频频域数据数量的数字。
-
getMaxDecibels()
:- 描述:获取音频分析器的最大分贝值。
- 参数:无
- 返回值:表示最大分贝值的数字。
-
setMaxDecibels(maxDecibels)
:- 描述:设置音频分析器的最大分贝值。
- 参数:
maxDecibels
(Number):要设置的最大分贝值。
- 返回值:无
-
getMinDecibels()
:- 描述:获取音频分析器的最小分贝值。
- 参数:无
- 返回值:表示最小分贝值的数字。
-
setMinDecibels(minDecibels)
:- 描述:设置音频分析器的最小分贝值。
- 参数:
minDecibels
(Number):要设置的最小分贝值。
- 返回值:无
-
getSmoothingTimeConstant()
:- 描述:获取音频分析器的平滑时间常数。
- 参数:无
- 返回值:表示平滑时间常数的数字。
-
setSmoothingTimeConstant(smoothingTimeConstant)
:- 描述:设置音频分析器的平滑时间常数。
- 参数:
smoothingTimeConstant
(Number):要设置的平滑时间常数。
- 返回值:无
属性(Properties)
analyser
(AnalyserNode):表示音频分析器的AnalyserNode
实例。data
(Uint8Array):表示音频频域数据的Uint8Array
数组。fftSize
(Number):表示音频分析器的 FFT(快速傅里叶变换)大小。frequencyBinCount
(Number):表示音频频域数据的数量。minDecibels
(Number):表示音频分析器的最小分贝值。maxDecibels
(Number):表示音频分析器的最大分贝值。smoothingTimeConstant
(Number):表示音频分析器的平滑时间常数。
THREE.AudioAnalyser
类提供了一组方法和属性,允许开发人员对音频进行频谱分析,并获取音频的频域数据和时域数据。
demo 源码
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webaudio - sandbox</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 id="song" preload="auto" style="display: none">
<source src="sounds/358232_j_s_song.ogg" type="audio/ogg">
<source src="sounds/358232_j_s_song.mp3" type="audio/mpeg">
</audio>
<audio id="skullbeatz" 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>
<audio id="utopia" loop preload="auto" style="display: none">
<source src="sounds/Project_Utopia.ogg" type="audio/ogg">
<source src="sounds/Project_Utopia.mp3" type="audio/mpeg">
</audio>
<div id="overlay">
<button id="startButton">Play</button>
</div>
<div id="info">
<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webaudio - sandbox<br/>
music by <a href="http://www.newgrounds.com/audio/listen/358232" target="_blank" rel="noopener">larrylarrybb</a>,
<a href="http://www.newgrounds.com/audio/listen/376737" target="_blank" rel="noopener">skullbeatz</a> and
<a href="http://opengameart.org/content/project-utopia-seamless-loop" target="_blank" rel="noopener">congusbongus</a><br/><br/>
navigate with WASD / arrows / mouse
</div>
<script type="importmap">
{
"imports": {
"three": "../build/three.module.js",
"three/addons/": "./jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
import { FirstPersonControls } from 'three/addons/controls/FirstPersonControls.js';
let camera, controls, scene, renderer, light;
let material1, material2, material3;
let analyser1, analyser2, analyser3;
const clock = new THREE.Clock();
const startButton = document.getElementById('startButton');
startButton.addEventListener('click', init);
function init() {
const overlay = document.getElementById('overlay');
overlay.remove();
// 创建相机和监听器
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(0, 25, 0);
const listener = new THREE.AudioListener();
camera.add(listener);
// 创建场景和光源
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x000000, 0.0025);
light = new THREE.DirectionalLight(0xffffff, 3);
light.position.set(0, 0.5, 1).normalize();
scene.add(light);
// 创建材质
const sphere = new THREE.SphereGeometry(20, 32, 16);
material1 = new THREE.MeshPhongMaterial({ color: 0xffaa00, flatShading: true, shininess: 0 });
material2 = new THREE.MeshPhongMaterial({ color: 0xff2200, flatShading: true, shininess: 0 });
material3 = new THREE.MeshPhongMaterial({ color: 0x6622aa, flatShading: true, shininess: 0 });
// 创建声音球体
const mesh1 = new THREE.Mesh(sphere, material1);
mesh1.position.set(-250, 30, 0);
scene.add(mesh1);
const sound1 = new THREE.PositionalAudio(listener);
const songElement = document.getElementById('song');
sound1.setMediaElementSource(songElement);
sound1.setRefDistance(20);
songElement.play();
mesh1.add(sound1);
const mesh2 = new THREE.Mesh(sphere, material2);
mesh2.position.set(250, 30, 0);
scene.add(mesh2);
const sound2 = new THREE.PositionalAudio(listener);
const skullbeatzElement = document.getElementById('skullbeatz');
sound2.setMediaElementSource(skullbeatzElement);
sound2.setRefDistance(20);
skullbeatzElement.play();
mesh2.add(sound2);
const mesh3 = new THREE.Mesh(sphere, material3);
mesh3.position.set(0, 30, -250);
scene.add(mesh3);
const sound3 = new THREE.PositionalAudio(listener);
const oscillator = listener.context.createOscillator();
oscillator.type = 'sine';
oscillator.frequency.setValueAtTime(144, sound3.context.currentTime);
oscillator.start(0);
sound3.setNodeSource(oscillator);
sound3.setRefDistance(20);
sound3.setVolume(0.5);
mesh3.add(sound3);
// 创建声音分析器
analyser1 = new THREE.AudioAnalyser(sound1, 32);
analyser2 = new THREE.AudioAnalyser(sound2, 32);
analyser3 = new THREE.AudioAnalyser(sound3, 32);
// 创建全局背景音乐
const sound4 = new THREE.Audio(listener);
const utopiaElement = document.getElementById('utopia');
sound4.setMediaElementSource(utopiaElement);
sound4.setVolume(0.5);
utopiaElement.play();
// 创建地面网格
const helper = new THREE.GridHelper(1000, 10, 0x444444, 0x444444);
helper.position.y = 0.1;
scene.add(helper);
// 创建控制器
const SoundControls = function () {
this.master = listener
.getMasterVolume();
this.firstSphere = sound1.getVolume();
this.secondSphere = sound2.getVolume();
this.thirdSphere = sound3.getVolume();
this.Ambient = sound4.getVolume();
};
const GeneratorControls = function () {
this.frequency = oscillator.frequency.value;
this.wavetype = oscillator.type;
};
const gui = new GUI();
const soundControls = new SoundControls();
const generatorControls = new GeneratorControls();
const volumeFolder = gui.addFolder('声音音量');
const generatorFolder = gui.addFolder('声音生成器');
// 声音音量控制
volumeFolder.add(soundControls, 'master').min(0.0).max(1.0).step(0.01).onChange(function () {
listener.setMasterVolume(soundControls.master);
});
volumeFolder.add(soundControls, 'firstSphere').min(0.0).max(1.0).step(0.01).onChange(function () {
sound1.setVolume(soundControls.firstSphere);
});
volumeFolder.add(soundControls, 'secondSphere').min(0.0).max(1.0).step(0.01).onChange(function () {
sound2.setVolume(soundControls.secondSphere);
});
volumeFolder.add(soundControls, 'thirdSphere').min(0.0).max(1.0).step(0.01).onChange(function () {
sound3.setVolume(soundControls.thirdSphere);
});
volumeFolder.add(soundControls, 'Ambient').min(0.0).max(1.0).step(0.01).onChange(function () {
sound4.setVolume(soundControls.Ambient);
});
volumeFolder.open();
// 声音生成器控制
generatorFolder.add(generatorControls, 'frequency').min(50.0).max(5000.0).step(1.0).onChange(function () {
oscillator.frequency.setValueAtTime(generatorControls.frequency, listener.context.currentTime);
});
generatorFolder.add(generatorControls, 'wavetype', ['sine', 'square', 'sawtooth', 'triangle']).onChange(function () {
oscillator.type = generatorControls.wavetype;
});
generatorFolder.open();
// 创建渲染器
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 创建控制器
controls = new FirstPersonControls(camera, renderer.domElement);
controls.movementSpeed = 70;
controls.lookSpeed = 0.05;
controls.lookVertical = false;
// 监听窗口大小变化
window.addEventListener('resize', onWindowResize);
animate();
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
controls.handleResize();
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
const delta = clock.getDelta();
controls.update(delta);
material1.emissive.b = analyser1.getAverageFrequency() / 256;
material2.emissive.b = analyser2.getAverageFrequency() / 256;
material3.emissive.b = analyser3.getAverageFrequency() / 256;
renderer.render(scene, camera);
}
</script>
</body>
</html>