mcpField
T
threejs-impl-audio

threejs-impl-audio

github.com/impertio-studio开发23134 次安装30 周前更新
代码仓库

关于 threejs-impl-audio

面向 Three.js 开发者的场景音频实现参考技能,介绍普通播放、空间音频、文件加载及频率分析。也说明浏览器对用户交互和音频上下文的要求。

主要功能

  1. 01音频监听器与播放设置
  2. 02全局音频和 3D 空间音频
  3. 03音频文件加载与播放控制
  4. 04浏览器音频交互要求
  5. 05用于可视化的频率分析

适用场景

  1. 01添加背景音乐或 UI 音效
  2. 02在场景中放置随距离变化的声音
  3. 03可视化音频频率数据

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/impertio-studio/three.js-claude-skill-package --skill threejs-impl-audio

安装后在 Claude Code 中输入/threejs-impl-audio确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
anti-patterns.md
examples.md
methods.md

详细介绍

threejs-impl-audio

快速参考

类层次结构
EventDispatcher
  └── Object3D
        ├── AudioListener    (receiver — attach to camera)
        ├── Audio            (non-positional — background music, UI sounds)
        └── PositionalAudio  (3D spatial — attached to scene objects)

辅助类:

  • AudioLoader — 将音频文件加载到 AudioBuffer
  • AudioAnalyser — 用于可视化的实时频率分析
架构概览
组件作用附加到
AudioListener虚拟耳朵(Web Audio API 输出端)摄像机(始终)
Audio非位置音效(任何位置的音量都相同)任意 Object3D 或场景
PositionalAudio3D 空间音效(音量取决于距离)场景中的网格或 Object3D
AudioLoader异步音频文件加载器不适用(工具)
AudioAnalyserFFT 频率数据提取器包装一个 Audio 实例
重要警告

绝不要在未先确保用户交互后已恢复 AudioContext 的情况下调用 sound.play()。现代浏览器始终会挂起 AudioContext,直到发生用户手势(点击、轻触或按键)。

绝不要在同一场景中创建多个 AudioListener。多个监听器会导致未定义的空间化行为。

绝不要设置 autoplay = true 并期待无需用户交互即可播放。浏览器会静默阻止播放。

始终将 AudioListener 附加到摄像机。如果附加到其他对象,空间音频计算会使用错误的参考位置。

始终在用户交互处理程序中调用 listener.context.resume(),然后再播放任何音频。

绝不要忘记处理 AudioLoader.load() 中的 onError 回调。音频文件缺失时,如果没有错误处理,加载会静默失败。


AudioListener 设置

AudioListener 是场景的虚拟麦克风。它封装了 Web Audio API 的 AudioContext 和 AudioDestinationNode。

import * as THREE from 'three';

const listener = new THREE.AudioListener();
camera.add( listener ); // ALWAYS add to camera
主音量控制
listener.setMasterVolume( 0.8 ); // range [0, 1]
const vol = listener.getMasterVolume(); // returns 0.8
全局音频滤波器
const filter = listener.context.createBiquadFilter();
filter.type = 'lowpass';
filter.frequency.value = 1000;
listener.setFilter( filter );
// Later: listener.removeFilter();

Audio(非位置音效)

使用 Audio 播放背景音乐、环境音景和 UI 反馈音效。无论监听器的位置如何,音量都相同。

加载和播放
const sound = new THREE.Audio( listener );
const audioLoader = new THREE.AudioLoader();

audioLoader.load( 'music.mp3', ( buffer ) => {
    sound.setBuffer( buffer );
    sound.setLoop( true );
    sound.setVolume( 0.5 );
    // Do NOT call sound.play() here — wait for user interaction
});
遵守自动播放策略(必须)
document.addEventListener( 'click', () => {
    if ( listener.context.state === 'suspended' ) {
        listener.context.resume();
    }
    if ( !sound.isPlaying ) {
        sound.play();
    }
}, { once: true } );
播放控制
sound.play();                    // start playback
sound.pause();                   // pause (resume with play())
sound.stop();                    // stop and reset to beginning
sound.setPlaybackRate( 1.5 );   // 1.5x speed
sound.setDetune( -100 );        // pitch down 1 semitone (100 cents)
其他音源
// HTML5 media element (for streaming large files)
const audioEl = new Audio( 'long-track.mp3' );
sound.setMediaElementSource( audioEl );

// Microphone input
navigator.mediaDevices.getUserMedia( { audio: true } ).then( ( stream ) => {
    sound.setMediaStreamSource( stream );
});

PositionalAudio(3D 空间音效)

使用 PositionalAudio 播放场景中某个位置发出的声音。音量和立体声声像会随监听器的距离和朝向变化。

基本设置
const positionalSound = new THREE.PositionalAudio( listener );

audioLoader.load( 'engine.ogg', ( buffer ) => {
    positionalSound.setBuffer( buffer );
    positionalSound.setRefDistance( 20 );
    positionalSound.setRolloffFactor( 1 );
    positionalSound.setDistanceModel( 'inverse' );
    positionalSound.setLoop( true );
    positionalSound.setVolume( 0.5 );
});

mesh.add( positionalSound ); // sound position follows the mesh
距离模型决策树
模型适用场景行为
'inverse'(默认)真实环境渐进衰减;永远不会降至零
'linear'可控范围(例如基于房间的场景)音量在 maxDistance 处降至零
'exponential'强烈的近远对比快速衰减曲线

参数选择:

  • refDistance — 音量为 100% 时的距离。将其设为场景单位中的“舒适聆听范围”。典型值:1 到 20。
  • maxDistance — 仅对 'linear' 模型有效。'inverse' 和 'exponential' 会忽略此参数。
  • rolloffFactor — 音量降低的速度。对于 'inverse':1 = 真实衰减。对于 'linear':1 = 完整范围。值越高,衰减越快。
定向音频锥体
positionalSound.setDirectionalCone( 180, 360, 0.1 );
// coneInnerAngle: 180° — full volume zone
// coneOuterAngle: 360° — transition zone
// coneOuterGain: 0.1  — volume outside outer cone (10%)

AudioLoader

始终使用 AudioLoader 加载音频文件。它会通过回调返回一个 AudioBuffer。

const loader = new THREE.AudioLoader();

loader.load(
    'sound.ogg',
    ( buffer ) => { sound.setBuffer( buffer ); },   // onLoad
    ( xhr ) => { console.log( (xhr.loaded / xhr.total * 100) + '% loaded' ); }, // onProgress
    ( err ) => { console.error( 'Audio load failed:', err ); }  // onError — ALWAYS handle
);

支持的格式: MP3、OGG、WAV、AAC。OGG 的压缩率和音质表现最佳,但 Safari 不支持。为确保跨浏览器兼容性,始终提供 MP3 作为备用格式。


AudioAnalyser

封装 Web Audio API 的 AnalyserNode,用于实时频率可视化。

const analyser = new THREE.AudioAnalyser( sound, 256 );
// fftSize MUST be a power of 2: 32, 64, 128, 256, 512, 1024, 2048

function animate() {
    requestAnimationFrame( animate );

    const data = analyser.getFrequencyData();    // Uint8Array, length = fftSize / 2
    const avg = analyser.getAverageFrequency();  // number (0-255)

    // Drive visuals from audio data
    mesh.scale.y = 1 + avg / 128;
    renderer.render( scene, camera );
}
频率数据详情
  • getFrequencyData() 返回一个包含 fftSize / 2 个元素的 Uint8Array
  • 每个元素的范围为 0 到 255(分贝幅度)
  • 索引 0 对应最低频率,最后一个索引对应最高频率
  • getAverageFrequency() 返回所有频段的算术平均值

集成清单

  1. 创建一个 AudioListener 并将其添加到摄像机
  2. 使用该监听器创建 Audio 或 PositionalAudio
  3. 使用 AudioLoader 加载音频
  4. 设置缓冲区、音量、循环和距离属性
  5. 添加用户交互处理器以恢复 AudioContext
  6. 仅在用户交互后调用 play()
  7. 对于空间音频:将 PositionalAudio 添加为目标网格的子级

参考链接

官方来源

评论

支持 Markdown