Last active
May 6, 2019 09:41
-
-
Save timetocode/c07193efa0628c9d25298631568ff16d to your computer and use it in GitHub Desktop.
Pooled sounds for Babylon.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let basePath = 'http://localhost:8086' | |
if (typeof window === 'undefined') { | |
basePath = 'http://localhost:8086/' | |
} | |
if (process && process.env && process.env.NODE_ENV === 'production') { | |
basePath = `https://somedomain.io/` | |
} | |
const sounds = new Map() | |
let assetsManager = null | |
let scene = null | |
const setScene = (value) => { | |
scene = value | |
} | |
const setAssetsManager = (value) => { | |
assetsManager = value | |
} | |
const add = (soundFilename) => { | |
if (!assetsManager || !scene) { | |
throw new Error('SoundAtlas scene or assetsManager was null, unable to add sound.') | |
} | |
const binaryTask = assetsManager.addBinaryFileTask(`BinaryTask load ${soundFilename}`, `${basePath}${soundFilename}`) | |
binaryTask.onSuccess = (task) => { | |
// solo sounds are non-spatial variants (was too difficult to change a spatial to sound to non-spatial after creation | |
const soloSound = new BABYLON.Sound(soundFilename + '-solo', task.data, scene, null, { spatialSound: false }) | |
sounds.set(soundFilename + '-solo', soloSound) | |
//console.log('creating...', soundFilename, soundFilename + '-solo') | |
const sound = soloSound.clone() | |
sound.spatialSound = true//new BABYLON.Sound(soundFilename, task.data, scene, null, { spatialSound: true }) | |
sounds.set(soundFilename, sound) | |
} | |
binaryTask.onError = (task, message, err) => { | |
console.log('Sound Load Error', message, err) | |
} | |
} | |
const dispose = () => { | |
sounds.forEach(sound => { | |
sound.dispose() | |
}) | |
sounds.clear() | |
} | |
// does not work as well as it may seem.. some of these options can't be mutated | |
const applyOptions = (sound, options) => { | |
if (options) { | |
sound.autoplay = options.autoplay || false | |
sound.loop = options.loop || false | |
if (typeof options.volume !== 'undefined') { | |
sound._volume = options.volume | |
sound.setVolume(options.volume) | |
} | |
sound.spatialSound = options.spatialSound || false | |
sound.maxDistance = options.maxDistance || 100 | |
sound.useCustomAttenuation = options.useCustomAttenuation || false | |
sound.rolloffFactor = options.rolloffFactor || 1 | |
sound.refDistance = options.refDistance || 1 | |
sound.distanceModel = options.distanceModel || 'linear' | |
sound._playbackRate = options.playbackRate || 1 | |
sound.setPlaybackRate(options.playbackRate || 1) | |
// doubt this works | |
sound._streaming = options.streaming || false | |
} | |
} | |
BABYLON.Sound.FromAtlas = (name, filepath, scene, options) => { | |
const cachedSound = sounds.get(filepath) | |
if (!cachedSound) { | |
throw new Error(filepath + ' Sound not found in SoundAtlas') | |
} | |
const sound = cachedSound.clone() | |
sound.name = name | |
applyOptions(sound, options) | |
// forces autoplay if it was set | |
if (options && options.autoplay) { | |
sound.play() | |
} | |
return sound | |
} | |
export default { setScene, setAssetsManager, add, dispose } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class SoundPool { | |
constructor() { | |
this.scene = null | |
this.soundsManual = {} | |
this.sounds = {} | |
this.allocations = 0 | |
this.allocationsManual = 0 | |
// debug check | |
//setInterval(() => { | |
// console.log('sound pool', this.sounds, this.allocations, this.allocationsManual) | |
//}, 3000) | |
} | |
init(scene) { | |
this.scene = scene | |
} | |
allocate(name) { | |
const sound = BABYLON.Sound.FromAtlas(name, name, this.scene) | |
sound.onEndedObservable.add(() => { | |
//console.log('returning sound') | |
this.release(sound) | |
}) | |
this.sounds[name].push(sound) | |
this.allocations++ | |
} | |
allocateManual(name) { | |
const sound = BABYLON.Sound.FromAtlas(name, name, this.scene) | |
this.soundsManual[name].push(sound) | |
this.allocationsManual++ | |
} | |
// gets or creates a sound and sound is automatically returned to pool when play finishes | |
get(name) { | |
if (!this.sounds[name]) { | |
this.sounds[name] = [] | |
} | |
if (this.sounds[name].length === 0) { | |
this.allocate(name) | |
} | |
return this.sounds[name].pop() | |
} | |
// gets or creates a sound, does not return to pool (must call releaseManual to return it) | |
// for use when you have some code that may start playing the sound again on its own | |
getManual(name) { | |
if (!this.soundsManual[name]) { | |
this.soundsManual[name] = [] | |
} | |
if (this.soundsManual[name].length === 0) { | |
this.allocateManual(name) | |
} | |
return this.soundsManual[name].pop() | |
} | |
release(obj) { | |
this.sounds[obj.name].push(obj) | |
} | |
releaseManual(obj) { | |
this.soundsManual[obj.name].push(obj) | |
} | |
} | |
const singleton = new SoundPool() | |
export default singleton |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment