in src/common.speech/SynthesisAdapterBase.ts [302:466]
protected async receiveMessage(): Promise<void> {
try {
const connection: IConnection = await this.fetchConnection();
const message: ConnectionMessage = await connection.read();
if (this.receiveMessageOverride !== undefined) {
return this.receiveMessageOverride();
}
if (this.privIsDisposed) {
// We're done.
return;
}
// indicates we are draining the queue and it came with no message;
if (!message) {
if (!this.privSynthesisTurn.isSynthesizing) {
return;
} else {
return this.receiveMessage();
}
}
this.privServiceHasSentMessage = true;
const connectionMessage = SpeechConnectionMessage.fromConnectionMessage(message);
if (connectionMessage.requestId.toLowerCase() === this.privSynthesisTurn.requestId.toLowerCase()) {
switch (connectionMessage.path.toLowerCase()) {
case "turn.start":
this.privSynthesisTurn.onServiceTurnStartResponse();
break;
case "response":
this.privSynthesisTurn.onServiceResponseMessage(connectionMessage.textBody);
break;
case "audio":
if (this.privSynthesisTurn.streamId.toLowerCase() === connectionMessage.streamId.toLowerCase()
&& !!connectionMessage.binaryBody) {
this.privSynthesisTurn.onAudioChunkReceived(connectionMessage.binaryBody);
if (!!this.privSpeechSynthesizer.synthesizing) {
try {
const audioWithHeader = SynthesisAdapterBase.addHeader(connectionMessage.binaryBody, this.privSynthesisTurn.audioOutputFormat);
const ev: SpeechSynthesisEventArgs = new SpeechSynthesisEventArgs(
new SpeechSynthesisResult(
this.privSynthesisTurn.requestId,
ResultReason.SynthesizingAudio,
audioWithHeader));
this.privSpeechSynthesizer.synthesizing(this.privSpeechSynthesizer, ev);
} catch (error) {
// Not going to let errors in the event handler
// trip things up.
}
}
if (this.privSessionAudioDestination !== undefined) {
this.privSessionAudioDestination.write(connectionMessage.binaryBody);
}
}
break;
case "audio.metadata":
const metadataList = SynthesisAudioMetadata.fromJSON(connectionMessage.textBody).Metadata;
for (const metadata of metadataList) {
switch (metadata.Type) {
case MetadataType.WordBoundary:
this.privSynthesisTurn.onWordBoundaryEvent(metadata.Data.text.Text);
const wordBoundaryEventArgs: SpeechSynthesisWordBoundaryEventArgs = new SpeechSynthesisWordBoundaryEventArgs(
metadata.Data.Offset,
metadata.Data.text.Text,
metadata.Data.text.Length,
this.privSynthesisTurn.currentTextOffset);
if (!!this.privSpeechSynthesizer.wordBoundary) {
try {
this.privSpeechSynthesizer.wordBoundary(this.privSpeechSynthesizer, wordBoundaryEventArgs);
} catch (error) {
// Not going to let errors in the event handler
// trip things up.
}
}
break;
case MetadataType.Bookmark:
const bookmarkEventArgs: SpeechSynthesisBookmarkEventArgs = new SpeechSynthesisBookmarkEventArgs(
metadata.Data.Offset,
metadata.Data.Bookmark);
if (!!this.privSpeechSynthesizer.bookmarkReached) {
try {
this.privSpeechSynthesizer.bookmarkReached(this.privSpeechSynthesizer, bookmarkEventArgs);
} catch (error) {
// Not going to let errors in the event handler
// trip things up.
}
}
break;
case MetadataType.Viseme:
this.privSynthesisTurn.onVisemeMetadataReceived(metadata);
if (metadata.Data.IsLastAnimation) {
const visemeEventArgs: SpeechSynthesisVisemeEventArgs = new SpeechSynthesisVisemeEventArgs(
metadata.Data.Offset,
metadata.Data.VisemeId,
this.privSynthesisTurn.getAndClearVisemeAnimation());
if (!!this.privSpeechSynthesizer.visemeReceived) {
try {
this.privSpeechSynthesizer.visemeReceived(this.privSpeechSynthesizer, visemeEventArgs);
} catch (error) {
// Not going to let errors in the event handler
// trip things up.
}
}
}
break;
}
}
break;
case "turn.end":
this.privSynthesisTurn.onServiceTurnEndResponse();
let result: SpeechSynthesisResult;
try {
const audioBuffer: ArrayBuffer = await this.privSynthesisTurn.getAllReceivedAudioWithHeader();
result = new SpeechSynthesisResult(
this.privSynthesisTurn.requestId,
ResultReason.SynthesizingAudioCompleted,
audioBuffer
);
if (!!this.privSuccessCallback) {
this.privSuccessCallback(result);
}
} catch (error) {
if (!!this.privErrorCallback) {
this.privErrorCallback(error);
}
}
if (this.privSpeechSynthesizer.synthesisCompleted) {
try {
this.privSpeechSynthesizer.synthesisCompleted(
this.privSpeechSynthesizer,
new SpeechSynthesisEventArgs(result)
);
} catch (e) {
// Not going to let errors in the event handler
// trip things up.
}
}
break;
default:
if (!this.processTypeSpecificMessages(connectionMessage)) {
// here are some messages that the derived class has not processed, dispatch them to connect class
if (!!this.privServiceEvents) {
this.serviceEvents.onEvent(new ServiceEvent(connectionMessage.path.toLowerCase(), connectionMessage.textBody));
}
}
}
}
return this.receiveMessage();
} catch (e) {
// TODO: What goes here?
}
}