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;
/**
* Audio buffer for sound to indicate that listending has started.
* @type {bufferSourceNode}
* Player for sound to indicate that listending has started.
* @type {SoundPlayer}
* @private
*/
this._startSoundBuffer = null;
this._startSoundPlayer = null;
/**
* Audio buffer for sound to indicate that listending has ended.
* @type {bufferSourceNode}
* Player for for sound to indicate that listending has ended.
* @type {SoundPlayer}
* @private
*/
this._endSoundBuffer = null;
this._endSoundPlayer = null;
/**
@ -198,13 +198,13 @@ class Scratch3SpeechBlocks {
*/
_loadUISounds () {
const startSoundBuffer = assetData['speech-rec-start.mp3'];
this._decodeSound(startSoundBuffer).then(buffer => {
this._startSoundBuffer = buffer;
this._decodeSound(startSoundBuffer).then(player => {
this._startSoundPlayer = player;
});
const endSoundBuffer = assetData['speech-rec-end.mp3'];
this._decodeSound(endSoundBuffer).then(buffer => {
this._endSoundBuffer = buffer;
this._decodeSound(endSoundBuffer).then(player => {
this._endSoundPlayer = player;
});
}
@ -215,43 +215,39 @@ class Scratch3SpeechBlocks {
* @private
*/
_decodeSound (soundBuffer) {
const context = this.runtime.audioEngine && this.runtime.audioEngine.audioContext;
const engine = this.runtime.audioEngine;
if (!context) {
return Promise.reject(new Error('No Audio Context Detected'));
if (!engine) {
return Promise.reject(new Error('No Audio Engine Detected'));
}
// Check for newer promise-based API
if (context.decodeAudioData.length === 1) {
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)
)
);
}
return engine.decodeSoundPlayer({data: {buffer: soundBuffer}});
}
/**
* 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.
* @private
*/
_playSound (buffer) {
_playSound (player) {
if (this.runtime.audioEngine === null) return;
const context = this.runtime.audioEngine.audioContext;
const bufferSource = context.createBufferSource();
bufferSource.buffer = buffer;
bufferSource.connect(this.runtime.audioEngine.input);
bufferSource.start();
if (player.isPlaying) {
// Take the internal player state and create a new player with it.
// `.play` does this internally but then instructs the sound to
// stop.
player.take();
}
const engine = this.runtime.audioEngine;
const chain = engine.createEffectChain();
player.connect(chain);
player.play();
return new Promise(resolve => {
bufferSource.onended = () => {
player.once('stop', () => {
resolve();
};
});
});
}
@ -727,7 +723,7 @@ class Scratch3SpeechBlocks {
// 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.
// 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._utteranceForEdgeTrigger = '';
const speechPromise = new Promise(resolve => {
@ -737,7 +733,7 @@ class Scratch3SpeechBlocks {
this._startListening();
}
});
return speechPromise.then(() => this._playSound(this._endSoundBuffer));
return speechPromise.then(() => this._playSound(this._endSoundPlayer));
});
}