Skip to main content

Spatial Audio & Speech

The xb.sound (or xb.core.sound) manager handles audio capture, playback, positional spatial audio, and Web Speech API wrappers.


Spatial (Positional) Audio​

Spatial audio pans, attenuates, and filters sounds based on the user's distance and orientation relative to an object in the virtual space.

To implement positional audio, attach a THREE.PositionalAudio node directly to the target object:

import * as THREE from 'three';
import * as xb from 'xrblocks';

class PositionalSoundScript extends xb.Script {
init() {
// 1. Get the Web Audio listener managed by the SDK
const listener = xb.core.sound.getAudioListener();

// 2. Create the PositionalAudio node
this.sound = new THREE.PositionalAudio(listener);

// 3. Configure audio parameters
this.sound.setRefDistance(0.5); // Distance where volume starts reducing
this.sound.setVolume(1.0);

// 4. Attach the sound node to the parent object
this.add(this.sound);
}

playAudio(audioBuffer) {
// Play a preloaded decoded AudioBuffer
this.sound.setBuffer(audioBuffer);
this.sound.play();
}
}

Microphone Recording & Playback​

XR Blocks supports direct microphone capture (e.g., for sending speech files to an AI model or storing voice memos).

Note: Microphone access prompts the user for permissions. Set options.permissions.microphone = true during startup.

// Start recording PCM audio from mic
await xb.core.sound.startRecording();

// Stop recording and retrieve buffer
const pcm = xb.core.sound.stopRecording(); // Returns ArrayBuffer of Int16 PCM
const sampleRate = xb.core.sound.getRecordingSampleRate();

// Play the captured PCM buffer
await xb.core.sound.playRecordedAudio(pcm, sampleRate);

Adjust the overall output levels:

xb.core.sound.setMasterVolume(0.8); // Set master volume between 0.0 and 1.0

Speech Recognition (Speech-to-Text)​

CoreSound creates the recognizer during initialization when options.sound.speechRecognizer.enabled is true. It is enabled by default. Configure it before xb.init() and listen for Three.js-style events:

class VoiceInput extends xb.Script {
init() {
const recognizer = xb.core.sound.speechRecognizer;
if (!recognizer) return;

recognizer.addEventListener('result', (event) => {
console.log('Transcript:', event.transcript);
console.log('Final:', event.isFinal);
});
recognizer.addEventListener('error', (event) => {
console.error('Recognition error:', event.error);
});

recognizer.start();
}
}

const options = new xb.Options();
options.permissions.microphone = true;
options.sound.speechRecognizer.lang = 'en-US';
options.sound.speechRecognizer.interimResults = true;
xb.add(new VoiceInput());
xb.init(options);

Speech Synthesis (Text-to-Speech)​

Enable the subsystem-managed synthesizer before initialization, then call its speak(text, lang, pitch, rate) method:

const options = new xb.Options();
options.sound.speechSynthesizer.enabled = true;
options.sound.speechSynthesizer.allowInterruptions = true;
xb.init(options);

await xb.core.sound.speechSynthesizer?.speak(
'Hello! Welcome to the XR experience.',
'en-US',
1.0, // pitch
1.0 // rate
);

// Stop speaking
xb.core.sound.speechSynthesizer?.cancel();

Speech recognition depends on the browser's Web Speech API and may be unavailable. Always guard the optional speechRecognizer and speechSynthesizer properties. For complete examples, see

demos/sound/main.js and src/sound/README.md.