Update speech extension to use new audio engine api since the old version no longer exists. (#1272)

This commit is contained in:
picklesrus 2018-07-15 13:23:14 -05:00 committed by Eric Rosenbaum
parent 3fa28cac35
commit bd83d66bff

View file

@ -155,18 +155,18 @@ class Scratch3SpeechBlocks {
this._audioPromise = null; this._audioPromise = null;
/** /**
* Audio buffer for sound to indicate that listending has started. * Player for sound to indicate that listending has started.
* @type {bufferSourceNode} * @type {SoundPlayer}
* @private * @private
*/ */
this._startSoundBuffer = null; this._startSoundPlayer = null;
/** /**
* Audio buffer for sound to indicate that listending has ended. * Player for for sound to indicate that listending has ended.
* @type {bufferSourceNode} * @type {SoundPlayer}
* @private * @private
*/ */
this._endSoundBuffer = null; this._endSoundPlayer = null;
/** /**
@ -198,13 +198,13 @@ class Scratch3SpeechBlocks {
*/ */
_loadUISounds () { _loadUISounds () {
const startSoundBuffer = assetData['speech-rec-start.mp3']; const startSoundBuffer = assetData['speech-rec-start.mp3'];
this._decodeSound(startSoundBuffer).then(buffer => { this._decodeSound(startSoundBuffer).then(player => {
this._startSoundBuffer = buffer; this._startSoundPlayer = player;
}); });
const endSoundBuffer = assetData['speech-rec-end.mp3']; const endSoundBuffer = assetData['speech-rec-end.mp3'];
this._decodeSound(endSoundBuffer).then(buffer => { this._decodeSound(endSoundBuffer).then(player => {
this._endSoundBuffer = buffer; this._endSoundPlayer = player;
}); });
} }
@ -215,43 +215,39 @@ class Scratch3SpeechBlocks {
* @private * @private
*/ */
_decodeSound (soundBuffer) { _decodeSound (soundBuffer) {
const context = this.runtime.audioEngine && this.runtime.audioEngine.audioContext; const engine = this.runtime.audioEngine;
if (!context) { if (!engine) {
return Promise.reject(new Error('No Audio Context Detected')); return Promise.reject(new Error('No Audio Engine Detected'));
} }
// Check for newer promise-based API // Check for newer promise-based API
if (context.decodeAudioData.length === 1) { return engine.decodeSoundPlayer({data: {buffer: soundBuffer}});
return context.decodeAudioData(soundBuffer);
} else { // eslint-disable-line no-else-return
// Fall back to callback API
return new Promise((resolve, reject) =>
context.decodeAudioData(soundBuffer,
buffer => resolve(buffer),
error => reject(error)
)
);
}
} }
/** /**
* Play the given sound. * Play the given sound.
* @param {ArrayBuffer} buffer The audio buffer to play. * @param {SoundPlayer} player The audio buffer to play.
* @returns {Promise} A promise that resoloves when the sound is done playing. * @returns {Promise} A promise that resoloves when the sound is done playing.
* @private * @private
*/ */
_playSound (buffer) { _playSound (player) {
if (this.runtime.audioEngine === null) return; if (this.runtime.audioEngine === null) return;
const context = this.runtime.audioEngine.audioContext; if (player.isPlaying) {
const bufferSource = context.createBufferSource(); // Take the internal player state and create a new player with it.
bufferSource.buffer = buffer; // `.play` does this internally but then instructs the sound to
bufferSource.connect(this.runtime.audioEngine.input); // stop.
bufferSource.start(); player.take();
}
const engine = this.runtime.audioEngine;
const chain = engine.createEffectChain();
player.connect(chain);
player.play();
return new Promise(resolve => { return new Promise(resolve => {
bufferSource.onended = () => { player.once('stop', () => {
resolve(); resolve();
}; });
}); });
} }
@ -727,7 +723,7 @@ class Scratch3SpeechBlocks {
// to be some lag between when the sound starts and when the socket message // to be some lag between when the sound starts and when the socket message
// callback is received. Perhaps we should play the sound after the socket is setup. // callback is received. Perhaps we should play the sound after the socket is setup.
// TODO: Question - Should we only play the sound if listening isn't already in progress? // TODO: Question - Should we only play the sound if listening isn't already in progress?
return this._playSound(this._startSoundBuffer).then(() => { return this._playSound(this._startSoundPlayer).then(() => {
this._phraseList = this._scanBlocksForPhraseList(); this._phraseList = this._scanBlocksForPhraseList();
this._utteranceForEdgeTrigger = ''; this._utteranceForEdgeTrigger = '';
const speechPromise = new Promise(resolve => { const speechPromise = new Promise(resolve => {
@ -737,7 +733,7 @@ class Scratch3SpeechBlocks {
this._startListening(); this._startListening();
} }
}); });
return speechPromise.then(() => this._playSound(this._endSoundBuffer)); return speechPromise.then(() => this._playSound(this._endSoundPlayer));
}); });
} }