kittykatattack / sound.js

A micro-library to load, play and generate sound effects and music for games and interactive applications
300 stars 44 forks source link

Play sound from PIXI.loader #8

Open webwarecode opened 8 years ago

webwarecode commented 8 years ago

Dear sir, congratulations on the excellent library and your work with Charm.js!

I'd like to know if it is possible to play a sound loaded in PIXI v3 and play it on sound.js? Could you help with the sample below? Any help would be greatly appreciated!

`var loader = PIXI.loader; loader.add("music", "sounds/music.mp3"); loader.load();

loader.on("progress", LoadProgressHandler); loader.on('complete', PlayLoadedSound); ... // makeSound("sounds/music.mp3", null, false, PIXI.loader.resources.music); ` Thanks in advance!

kittykatattack commented 8 years ago

Yes, it is possible, but you'll have to write a bit of custom code to do it. The biggest problem is that Pixi's loader doesn't have an audio decoder (I wish it did). But, Sound.js does have an audio decoder So, after the sound files are loaded using Pixi's loader, they need to be run through Sound.js's decoder before you can play them. It can take a few hundred milliseconds for sounds do decode, so if you try to play them before they've decoded, you won't hear anything. (You might get a "null" reference error.) That means you need to run a callback function when each sound has decoded, and, only after they've all been decoded, attempt to play them.

Here's an example. This is untested code modified from the working code in the Hexi game engine - it should get you close to what you need. (Hexi uses Pixi's loader to load sounds, and then uses Sound.js to decode them - just what you need need) If the flag allSoundsDecoded is true, you know you'll be able to play the sounds without errors.

//Variables to count the number of sound files and the sound files
//that have been decoded. If both these numbers are the same at
//some point, then we know all the sounds have been decoded and we
//can set `allSoundsDecoded` to `true`
var soundsToDecode = 0,
    soundsDecoded = 0,
    allSoundsDecoded = false;

//First, create a list of the kind of sound files we want to check
var soundExtensions = ["wav", "mp3", "ogg", "webm"];

//The `decodeHandler` will run when each sound file is decoded
var decodeHandler = function() {

  //Count 1 more sound as having been decoded
  soundsDecoded += 1;

  //If the decoded sounds match the number of sounds to decode,
  //then we know all the sounds have been decoded and we can call
  //`finishLoadingState`
  if (soundsToDecode === soundsDecoded) {

    // All sounds have been decoded.
    allSoundsDecoded = true;
  }
};

//Loop through all the loader's resources and look for sound files
Object.keys(PIXI.loader.resources).forEach(function(resource) {

  //Find the file extension of the asset
  var extension = resource.split(".").pop();

  //If one of the resource file extensions matches the sound file
  //extensions, then we know we have a sound file
  if(soundExtensions.indexOf(extension) !== -1){

    //Count one more sound to decode
    soundsToDecode += 1;

    //Create aliases for the sound's `xhr` object and `url` (its
    //file name)
    var xhr = PIXI.loader.resources[resource].xhr,
          url = PIXI.loader.resources[resource].url;

    //Create a sound sprite using`sound.js`'s
    //`makeSound` function. Notice the 4th argument is the loaded
    //sound's `xhr` object. Setting the 3rd argument to `false`
    //means that `makeSound` won't attempt to load the sounds
    //again. When the sound has been decoded, the `decodeHandler`
    //(see above!) will be run 
    var soundSprite = makeSound(url, decodeHandler.bind(this), false, xhr);
  }
});
webwarecode commented 8 years ago

Thank you very much for your quick and precise answer! It worked like magic! Looking into hexi code i've found the lines below, that help me a lot too.

var Resource = PIXI.loaders.Resource; Resource.setExtensionLoadType("mp3", Resource.LOAD_TYPE.XHR); Resource.setExtensionXhrType("mp3", Resource.XHR_RESPONSE_TYPE.BUFFER);

Best wishes and keep on the excellent work!

kittykatattack commented 8 years ago

Oh wow, that's great to know! I should actually wrap all that code up in a function and add it to this repository.

Sorry, I forgot to include that crucial configuration to Pixi's loader (which you found.) This is the code you need to configure Pixi's loader to load all sound file types as "array buffer" - which is what you need to decode them as sound files.

//Set default loading mechanism for sound file extensions to use XHR
    let Resource = PIXI.loaders.Resource;
    Resource.setExtensionLoadType("wav", Resource.LOAD_TYPE.XHR);
    Resource.setExtensionLoadType("mp3", Resource.LOAD_TYPE.XHR);
    Resource.setExtensionLoadType("ogg", Resource.LOAD_TYPE.XHR);
    Resource.setExtensionLoadType("webm", Resource.LOAD_TYPE.XHR);

    //Set default loading type for sound file extensions to be arraybuffer
    Resource.setExtensionXhrType("wav", Resource.XHR_RESPONSE_TYPE.BUFFER);
    Resource.setExtensionXhrType("mp3", Resource.XHR_RESPONSE_TYPE.BUFFER);
    Resource.setExtensionXhrType("ogg", Resource.XHR_RESPONSE_TYPE.BUFFER);
    Resource.setExtensionXhrType("webm", Resource.XHR_RESPONSE_TYPE.BUFFER);