rserota / wad

Web Audio DAW. Use the Web Audio API for dynamic sound synthesis. It's like jQuery for your ears.
MIT License
1.89k stars 160 forks source link

Determine if currently playing #96

Closed richtier closed 5 years ago

richtier commented 5 years ago

I would like to determine when wad has finished playing.

I have a play queue - so when one has finished the other can start.

I have asetInterval that simply checks isPlaying.

I've checked the code and docs and cannot see a callback or state to check.

rserota commented 5 years ago

The play() method of a wad object returns a promise, which resolves when that wad finishes playing. This makes it pretty easy to play a queue of wads in sequence, using async/await, or other promise methods. This is briefly mentioned in the docs, near https://github.com/rserota/wad#play. Does that help?

richtier commented 5 years ago

the promise seems to resolve immediately. I have:

    // samples is mp3 data provided by a websocket
    var blob = new Blob([samples]);
    var src = URL.createObjectURL(blob)
    var wadSound = new Wad({source: src});
    wadSound.then(function(){
        console.log('finished')
    })
    console.log('started')
  }

with a 5 second mp3 the console shows started and finished immediately

rserota commented 5 years ago

Hmm.... so, for one thing, the promise is returned from the play() method, not the constructor, like you've written above. I'm assuming that this error is only in the snippet above, and not in your actual code. Another potential issue is that because you're instantiating a wad object in a somewhat unusual way, it's possible that the constructor function doesn't properly detect the length of the audio. As a possible workaround, if you already know how long the audio clips are, you can manually assign the duration to the wad.

wadSound.defaultEnv.hold = 2.5 
wadSound.play().then(function(){
    console.log('hello') // this log will appear 2.5 seconds after calling play()
})
richtier commented 5 years ago

assuming this error is only in the snippet above

Correct :)

I think Alexa returns the length of the audio in milliseconds so I can set the hold time. Thanks.

richtier commented 5 years ago
  function getDuration(source) {
    return new Promise(function(resolve) {
      var audio = new Audio();
      audio.onloadedmetadata = function() {
        resolve(audio.duration);
      }
      audio.src = source;
    });
  }

  function playAudioHandler(samples) {
    var blob = new Blob([samples]);
    var source = URL.createObjectURL(blob)
    getDuration(source)
      .then(function(length) {
        this.wadSound = new Wad(getWadConfig({source: source}));
        wadSound.defaultEnv.hold = length;
        isPlaying = true;
        return this.wadSound.play({wait: 0})
      })
      .then(function(){
        isPlaying = false;
      });
  }