AlbertTJames Posted April 13, 2017 Share Posted April 13, 2017 Hi, I had trouble loading sounds and playing them directly at startup. I realised that the AssetManager calls the onFinish callback before loaded sounds _audioBuffer is set and are _readyToPlay. I dont know if it was a designed choice but it would be really useful either if the asset manager waited by default for the readytoplay flag to be set, or if there was an option to set when adding the job to the manager. Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted April 13, 2017 Share Posted April 13, 2017 Ping @davrous Quote Link to comment Share on other sites More sharing options...
davrous Posted April 13, 2017 Share Posted April 13, 2017 Hello, I'm not sure to understand your issue. Here's the doc I've written on AssetManager + Sounds: http://doc.babylonjs.com/overviews/playing_sounds_and_music#loading-a-sound-using-the-assets-manager using this PG sample: http://www.babylonjs-playground.com/#PCY1J#8 and this one is playing immediatly once loaded: http://www.babylonjs-playground.com/#PCY1J#38 Can you please share a PG of the issue you've got on your side? Thanks, David Quote Link to comment Share on other sites More sharing options...
AlbertTJames Posted April 13, 2017 Author Share Posted April 13, 2017 Looking at your PG I understand the way it was intended to work. The asset manager loads raw data, then you state for each sound a callback when the Sound object will be finished transforming the data into readable sound (_audioBuffer) ? I see how I can fix my problem better on my end, and I am not sure indeed that the behavior I am requesting is really relevant, my bad. To explain where my request come from is that I am building a little layer of abstraction above Babylon and I have a function that can load a bunch of assets and store them into an external object to be used by different scenes and interact with the website too. I was intended for user to simply call this function with an object like so: taskObject.assetsToLoad = { logo2: '/assets/experiment-js-light.svg', heldenklage: { path: '/assets/sounds/nietzscheHeldenklage.mp3', type: 'sound', }, } the function would return a promise resolving when the assetManager finished all its work. It was using the assetManager like that: http://www.babylonjs-playground.com/#PCY1J#40 Anyways.. I understand that I have to give a callback when creating the sound, but in this context it is not ideal. I will just make a bunch of separate promises waiting for the sounds to be ready to play before resolving the main loader. But I am curious, what takes time between AssetManager loading and the sound being processed ? Quote Link to comment Share on other sites More sharing options...
AlbertTJames Posted April 13, 2017 Author Share Posted April 13, 2017 So maybe - for this post not to be for nothing, here is the solution I am using to make sure the sounds are ready before resolving. The deferred function I am using is pretty basic, adapted from somewhere, can't remember where.. maybe bluebird: function Deferred() { this.resolve = null this.reject = null /* A newly created Pomise object. * Initially in pending state. */ this.promise = new Promise((resolve, reject) => { this.resolve = resolve this.reject = reject }) Object.freeze(this) } And there is the loading function, there is a lot of elements that will be useful to nobody, the two important part are surrounded by // IMPORTANT PART ++ // ? loadAssets(assetObject = mandatory(), scene = mandatory(), assetFolder = '') { if (assetObject.constructor !== Object) { throw new Error('TaskObject.loadAssets: assetObject is not an Object') } if ((assetFolder === '') && (typeof this.ASSETS_FOLDER !== 'undefined')) { assetFolder = this.ASSETS_FOLDER } const textureFormats = ['png', 'bmp', 'jpg', 'tiff', 'svg'] const soundFormats = ['wav', 'mp3', 'flac', 'aac', 'mp4', 'ogg'] const assetManager = new BABYLON.AssetsManager(scene) const R = this.R const binaryPromises = [] const names = Object.keys(assetObject) let field let type let path for (let i = 0; i < names.length; i++) { field = assetObject[names[i]] if (field.constructor === String) { path = this.ASSETS_FOLDER + field if (textureFormats.indexOf(R.getFormat(path)) !== -1) { type = 'texture' } else if (soundFormats.indexOf(R.getFormat(path)) !== -1) { type = 'sound' } else { console.warn('TaskObject.loadAssets: asset invalid or not implement with shorthand function') type = 'invalid' } } else if ((field.constructor === Object) && (Object.keys(field).includes(['path', 'type']))) { path = this.ASSETS_FOLDER + field.path type = field.type } else { console.warn('TaskObject.loadAssets: asset invalid or not implement with shorthand function') type = 'invalid' } if (type === 'texture') { const assetManagerTask = assetManager.addTextureTask(`${names[i]}Task`, path) assetManagerTask.onSuccess = function (task) { R.add({ textures: { [this.textureName]: task.texture, }, }) }.bind({ textureName: names[i], }) } else if (type === 'sound') { // IMPORTANT PART ++++++++++ // const assetManagerTask = assetManager.addBinaryFileTask(`${names[i]}Task`, path) assetManagerTask.onSuccess = function (task) { const isReady = new Deferred() binaryPromises.push(isReady.promise) R.add({ sounds: { [this.soundName]: new BABYLON.Sound(this.soundName, task.data, scene, isReady.resolve), }, }) }.bind({ soundName: names[i], }) } // TODO all the rest such as Meshes.. what else ? } /* --- Create a Deferred promise that will resolve after loading is complete --- */ const loadDeferred = new Deferred() assetManager.load() assetManager.onFinish = function onFinish(tasks) { debuglog('TaskObject.loadAssets: tasks completed', tasks) // IMPORTANT PART +++++ // Promise.all(binaryPromises).then(() => loadDeferred.resolve(tasks)) } return loadDeferred.promise } Anyways, thanks Wingnut 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.