fix: listen to ended event to note playback stopping

- Fix playing a sound a second time once the first playback finished
This commit is contained in:
Michael "Z" Goddard 2018-06-12 09:18:48 -04:00
parent a5702a7d49
commit 5c822e6542
No known key found for this signature in database
GPG key ID: 762CD40DD5349872

View file

@ -2,6 +2,8 @@ const {EventEmitter} = require('events');
const VolumeEffect = require('./effects/VolumeEffect'); const VolumeEffect = require('./effects/VolumeEffect');
const ON_ENDED = 'ended';
class SoundPlayer extends EventEmitter { class SoundPlayer extends EventEmitter {
constructor (audioEngine, {id, buffer}) { constructor (audioEngine, {id, buffer}) {
super(); super();
@ -17,31 +19,48 @@ class SoundPlayer extends EventEmitter {
this.initialized = false; this.initialized = false;
this.isPlaying = false; this.isPlaying = false;
this.playbackRate = 1; this.playbackRate = 1;
this.onEnd = this.onEnd.bind(this);
} }
onEnd () { /**
* Handle any event we have told the output node to listen for.
*/
handleEvent (event) {
if (event.type === ON_ENDED) {
this.onEnded();
}
}
onEnded () {
this.emit('stop'); this.emit('stop');
this.isPlaying = false;
} }
initialize () { _createSource () {
if (this.outputNode !== null) {
this.outputNode.removeEventListener(ON_ENDED, this);
this.outputNode.disconnect();
}
this.outputNode = this.audioEngine.audioContext.createBufferSource(); this.outputNode = this.audioEngine.audioContext.createBufferSource();
this.outputNode.playbackRate.value = this.playbackRate; this.outputNode.playbackRate.value = this.playbackRate;
this.outputNode.buffer = this.buffer; this.outputNode.buffer = this.buffer;
this.outputNode.addEventListener('end', this.onEnd); this.outputNode.addEventListener(ON_ENDED, this);
this.volumeEffect = new VolumeEffect(this.audioEngine, this, null);
this.initialized = true;
if (this.target !== null) { if (this.target !== null) {
this.connect(this.target); this.connect(this.target);
this.setPlaybackRate(this.playbackRate);
} }
} }
initialize () {
this.initialized = true;
this.volumeEffect = new VolumeEffect(this.audioEngine, this, null);
this._createSource();
}
connect (target) { connect (target) {
if (target === this.volumeEffect) { if (target === this.volumeEffect) {
this.outputNode.disconnect(); this.outputNode.disconnect();
@ -79,7 +98,7 @@ class SoundPlayer extends EventEmitter {
take () { take () {
if (this.outputNode) { if (this.outputNode) {
this.outputNode.removeEventListener('end', this.onEnd); this.outputNode.removeEventListener(ON_ENDED, this);
} }
const taken = new SoundPlayer(this.audioEngine, this); const taken = new SoundPlayer(this.audioEngine, this);
@ -119,6 +138,8 @@ class SoundPlayer extends EventEmitter {
if (!this.initialized) { if (!this.initialized) {
this.initialize(); this.initialize();
} else {
this._createSource();
} }
this.volumeEffect.set(this.volumeEffect.DEFAULT_VALUE); this.volumeEffect.set(this.volumeEffect.DEFAULT_VALUE);
@ -135,7 +156,7 @@ class SoundPlayer extends EventEmitter {
} }
this.volumeEffect.set(0); this.volumeEffect.set(0);
this.outputNode.stop(this.audioEngine.audioEngineoContext.currentTime + this.audioEngine.DECAY_TIME); this.outputNode.stop(this.audioEngine.audioContext.currentTime + this.audioEngine.DECAY_TIME);
this.isPlaying = false; this.isPlaying = false;
@ -154,6 +175,12 @@ class SoundPlayer extends EventEmitter {
this.emit('stop'); this.emit('stop');
} }
finished () {
return new Promise(resolve => {
this.once('stop', resolve);
});
}
setPlaybackRate (value) { setPlaybackRate (value) {
this.playbackRate = value; this.playbackRate = value;