Audio Components
The engine provides users with basic capabilities to load and play audio by encapsulating the Web Audio API:
AudioListener- Virtual audio listener component, needs to be used in conjunction with the audio sources belowStaticAudio- A position-independent audio source whose playback effect is unrelated to the ListenerPositionAudio- A position-based audio source whose playback effect changes with the relative position of the Listener
Static Audio
Plays audio independent of spatial position, such as global background music, sound effects, etc.
ts
import {AudioListener, StaticAudio} from '@orillusion/media-extention'
// Audio listener component. Static audio can be added to any object; here scene is used as an example
let listener = scene.addComponent(AudioListener)
// Create a static audio source
let audioObj = new Object3D()
let staticAudio = audioObj.addComponent(StaticAudio)
// Set the listener
staticAudio.setLisenter(listener)
// Load the audio
await staticAudio.load('https://cdn.orillusion.com/audio.ogg')
// Play the audio; the sound effect is independent of spatial position
staticAudio.play()ts
import { BoxGeometry, Camera3D, DirectLight, Engine3D, LitMaterial, KelvinUtil, MeshRenderer, Object3D, Scene3D, Vector3, Color, OrbitController, View3D, AtmosphericComponent } from '@orillusion/core';
import { StaticAudio, AudioListener } from '@orillusion/media-extention';
import * as dat from 'dat.gui';
class Static_Audio {
lightObj: Object3D;
scene: Scene3D;
camera: Object3D;
mats: any[];
audio: StaticAudio;
engine: Engine3D;
constructor() {}
async run() {
this.engine = await Engine3D.init({
setting: {
shadow: {
autoUpdate: true,
updateFrameRate: 1,
type: 'HARD',
shadowSize: 2048,
shadowBound: 200,
shadowBias: 0.002
}
}
});
this.scene = new Scene3D();
this.scene.addComponent(AtmosphericComponent);
this.camera = new Object3D();
this.camera.localPosition = new Vector3(0, 20, 50);
let mainCamera = this.camera.addComponent(Camera3D);
this.scene.addChild(this.camera);
mainCamera.perspective(60, this.engine.aspect, 0.1, 20000.0);
let orbit = this.camera.addComponent(OrbitController);
orbit.target = new Vector3(0, 4, 0);
orbit.minDistance = 10;
orbit.maxDistance = 200;
let view = new View3D();
view.scene = this.scene;
view.camera = mainCamera;
this.engine.startRenderView(view);
await this.initScene();
}
async initScene() {
{
let wall = new Object3D();
let mr = wall.addComponent(MeshRenderer);
mr.geometry = new BoxGeometry(40, 30, 1);
let mat = new LitMaterial();
mat.baseColor = new Color(1, 0, 0);
mr.material = mat;
this.scene.addChild(wall);
wall.z = -5;
}
{
let floor = new Object3D();
let mr = floor.addComponent(MeshRenderer);
mr.geometry = new BoxGeometry(3000, 1, 3000);
let mat = new LitMaterial();
mr.material = mat;
this.scene.addChild(floor);
}
/******** light *******/
{
this.lightObj = new Object3D();
this.lightObj.rotationX = 35;
this.lightObj.rotationY = 110;
this.lightObj.rotationZ = 0;
let directLight = this.lightObj.addComponent(DirectLight);
directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355);
directLight.castShadow = true;
directLight.intensity = 3;
this.scene.addChild(this.lightObj);
}
{
let group = new Object3D();
let speaker = await this.engine.res.loadGltf('https://cdn.orillusion.com/gltfs/speaker/scene.gltf');
speaker.localScale.set(4, 4, 4);
speaker.rotationX = -120;
//speaker.y = 1.5
group.addChild(speaker);
group.y = 2;
this.scene.addChild(group);
let listener = this.camera.addComponent(AudioListener);
let audio = group.addComponent(StaticAudio);
audio.setLisenter(listener);
await audio.load('https://cdn.orillusion.com/audio.ogg');
let buttons = {
play: () => {
audio.play();
},
pause: () => {
audio.pause();
},
stop: () => {
audio.stop();
},
volume: 1
};
let gui = new dat.GUI();
gui.addFolder('Orillusion');
gui.add(buttons, 'play');
gui.add(buttons, 'pause');
gui.add(buttons, 'stop');
gui.add(buttons, 'volume', 0, 1, 0.01).onChange((v) => {
audio.setVolume(v);
});
}
}
}
new Static_Audio().run();3D Spatial Audio
Audio playback based on 3D spatial position via PannerNode. The direction and volume of the sound are related to the relative position of the listener and the audio source.
ts
import {AudioListener, PositionAudio} from '@orillusion/media-extention'
let movingObj = new Object3D()
// Add an audio listener component, usually to a dynamically moving object, e.g. add it to the camera to simulate the user's spatial position
let listener = movingObj.addComponent(AudioListener)
// Create a spatial audio source
let audioObj = new Object3D()
let positionAudio = audioObj.addComponent(PositionAudio)
// Set the spatial parameters of the audio source; see the PannerNode API for details
positionAudio.refDistance = 10;
positionAudio.maxDistance = 100;
positionAudio.setDirectionalCone( 180, 230, 0.1 ); // coneInnerAngle, coneOuterAngle, coneOuterGain
...
// Display the spatial range of the audio
positionAudio.showHelper()
// Set the listener
positionAudio.setLisenter(listener)
// Load the audio
await positionAudio.load('https://cdn.orillusion.com/audio.ogg')
// Play the audio; the direction and volume of the sound change with the relative position of movingObj and audioObj
positionAudio.play()ts
import { BoxGeometry, Camera3D, DirectLight, Engine3D, LitMaterial, KelvinUtil, MeshRenderer, Object3D, Scene3D, Vector3, Color, OrbitController, View3D, AtmosphericComponent } from '@orillusion/core';
import { PositionAudio, AudioListener } from '@orillusion/media-extention';
import * as dat from 'dat.gui';
class Position_Audio {
lightObj: Object3D;
scene: Scene3D;
camera: Object3D;
mats: any[];
audio: PositionAudio;
engine: Engine3D;
private a = 40;
private b = 80;
private angle = 0;
constructor() {}
async run() {
this.engine = await Engine3D.init({
renderLoop: this.loop.bind(this),
setting: {
shadow: {
autoUpdate: true,
updateFrameRate: 1,
type: 'HARD',
shadowSize: 2048,
shadowBound: 250,
shadowBias: 0.002
}
}
});
this.scene = new Scene3D();
this.scene.addComponent(AtmosphericComponent);
this.camera = new Object3D();
this.camera.localPosition = new Vector3(0, 20, 50);
let mainCamera = this.camera.addComponent(Camera3D);
this.scene.addChild(this.camera);
mainCamera.perspective(60, this.engine.aspect, 0.1, 20000.0);
let orbit = this.camera.addComponent(OrbitController);
orbit.target = new Vector3(0, 4, 0);
orbit.minDistance = 10;
orbit.maxDistance = 200;
let view = new View3D();
view.scene = this.scene;
view.camera = mainCamera;
this.engine.startRenderView(view);
await this.initScene();
}
async initScene() {
{
let wall = new Object3D();
let mr = wall.addComponent(MeshRenderer);
mr.geometry = new BoxGeometry(40, 30, 1);
let mat = new LitMaterial();
mat.baseColor = new Color(1, 0, 0);
mr.material = mat;
this.scene.addChild(wall);
wall.z = -5;
}
{
let floor = new Object3D();
let mr = floor.addComponent(MeshRenderer);
mr.geometry = new BoxGeometry(3000, 1, 3000);
let mat = new LitMaterial();
mr.material = mat;
this.scene.addChild(floor);
}
/******** light *******/
{
this.lightObj = new Object3D();
this.lightObj.rotationX = 35;
this.lightObj.rotationY = 110;
this.lightObj.rotationZ = 0;
let directLight = this.lightObj.addComponent(DirectLight);
directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355);
directLight.castShadow = true;
directLight.intensity = 3;
this.scene.addChild(this.lightObj);
}
{
let [speaker, man, music] = await Promise.all([this.engine.res.loadGltf('https://cdn.orillusion.com/gltfs/speaker/scene.gltf'), this.engine.res.loadGltf('https://cdn.orillusion.com/gltfs/glb/CesiumMan.glb'), fetch('https://cdn.orillusion.com/audio.ogg').then((res) => res.arrayBuffer())]);
speaker.localScale.set(4, 4, 4);
speaker.rotationX = -120;
speaker.y = 0.5;
let group = new Object3D();
group.addChild(speaker);
group.y = 2;
this.scene.addChild(group);
man.name = 'man';
man.scaleX = 10;
man.scaleY = 10;
man.scaleZ = 10;
man.rotationX = -90;
man.rotationY = -90;
man.localPosition.set(0, 0.5, 30);
this.scene.addChild(man);
let listener = man.addComponent(AudioListener);
let audio = group.addComponent(PositionAudio);
audio.setLisenter(listener);
await audio.loadBuffer(music);
audio.refDistance = 10;
audio.maxDistance = 100;
audio.setDirectionalCone(180, 230, 0.1);
audio.showHelper();
let buttons = {
play: () => {
audio.play();
},
pause: () => {
audio.pause();
},
stop: () => {
audio.stop();
},
volume: 1,
'Toggle Helper': () => {
audio.toggleHelper();
}
};
let gui = new dat.GUI();
gui.addFolder('Orillusion');
gui.add(buttons, 'play');
gui.add(buttons, 'pause');
gui.add(buttons, 'stop');
gui.add(buttons, 'volume', 0, 1, 0.01).onChange((v) => {
audio.setVolume(v);
});
gui.add(buttons, 'Toggle Helper');
}
}
loop() {
let man = this.scene.getChildByName('man') as Object3D;
if (man) {
this.angle += 0.005;
man.x = this.a * Math.cos(this.angle);
man.z = this.b * Math.sin(this.angle) + 30;
man.rotationY -= (0.005 * 180) / Math.PI;
}
}
}
new Position_Audio().run();
