@voice-ping/cognitive-services-speech
Version:
VoicePing Cognitive Services Speech SDK for JavaScript forked from Microsoft
1 lines • 10.6 kB
Source Map (JSON)
{"version":3,"sources":["src/common.speech/SynthesisTurn.ts"],"names":[],"mappings":"AAGA,OAAO,EAGK,iBAAiB,EACzB,OAAO,EAEV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAGvE,OAAO,EAEH,oBAAoB,EAGvB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,yBAAyB;IACtC,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,uBAAuB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IAC/B,OAAO,EAAE,yBAAyB,CAAC;IACnC,KAAK,EAAE,uBAAuB,CAAC;CAClC;AAED,qBAAa,aAAa;IAEtB,IAAW,SAAS,IAAI,MAAM,CAE7B;IAED,IAAW,QAAQ,IAAI,MAAM,CAE5B;IAED,IAAW,QAAQ,CAAC,KAAK,EAAE,MAAM,EAEhC;IAED,IAAW,iBAAiB,IAAI,qBAAqB,CAEpD;IAED,IAAW,iBAAiB,CAAC,MAAM,EAAE,qBAAqB,EAEzD;IAED,IAAW,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC,CAEnD;IAED,IAAW,gBAAgB,IAAI,OAAO,CAErC;IAED,IAAW,cAAc,IAAI,OAAO,CAEnC;IAED,IAAW,iBAAiB,IAAI,MAAM,CAErC;IAGD,IAAW,aAAa,IAAI,MAAM,CAEjC;IAED,IAAW,gBAAgB,IAAI,WAAW,CASzC;IAED,IAAW,0BAA0B,IAAI,WAAW,CAanD;IACD,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,oBAAoB,CAAS;IACrC,OAAO,CAAC,kBAAkB,CAAkB;IAC5C,OAAO,CAAC,oBAAoB,CAAkB;IAC9C,OAAO,CAAC,iBAAiB,CAAa;IACtC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,gBAAgB,CAAoB;IAC5C,OAAO,CAAC,qBAAqB,CAAwB;IACrD,OAAO,CAAC,qBAAqB,CAA4B;IACzD,OAAO,CAAC,iBAAiB,CAAc;IACvC,OAAO,CAAC,2BAA2B,CAAc;IACjD,OAAO,CAAC,cAAc,CAAa;IACnC,OAAO,CAAC,uBAAuB,CAAa;IAC5C,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,wBAAwB,CAAoB;;IAU7C,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,CAAC,EAAE,iBAAiB,GAAG,IAAI;IAoBlH,oBAAoB,2DAG1B;IAEM,eAAe,6CAIrB;IAEM,8BAA8B,gDAQpC;IAEM,wBAAwB,iCAG9B;IAEM,wBAAwB,aAG9B;IAEM,0BAA0B,aAOhC;IAEM,oBAAoB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAU7C,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIvC,OAAO,2BAKb;IAEM,kBAAkB,IAAI,IAAI;IAIjC,SAAS,CAAC,OAAO,wCAEhB;IAED,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,UAAU,CAUjB;IAED,OAAO,CAAC,sBAAsB;CAUjC","file":"SynthesisTurn.d.ts","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT license.\n\nimport {\n createNoDashGuid,\n Deferred,\n Events, IAudioDestination,\n Promise,\n PromiseState\n} from \"../common/Exports\";\nimport { AudioOutputFormatImpl } from \"../sdk/Audio/AudioOutputFormat\";\nimport { PullAudioOutputStreamImpl } from \"../sdk/Audio/AudioOutputStream\";\nimport {SynthesisAdapterBase} from \"./SynthesisAdapterBase\";\nimport {\n ConnectingToSynthesisServiceEvent,\n SpeechSynthesisEvent,\n SynthesisStartedEvent,\n SynthesisTriggeredEvent,\n} from \"./SynthesisEvents\";\n\nexport interface ISynthesisResponseContext {\n serviceTag: string;\n}\n\nexport interface ISynthesisResponseAudio {\n type: string;\n streamId: string;\n}\n\nexport interface ISynthesisResponse {\n context: ISynthesisResponseContext;\n audio: ISynthesisResponseAudio;\n}\n\nexport class SynthesisTurn {\n\n public get requestId(): string {\n return this.privRequestId;\n }\n\n public get streamId(): string {\n return this.privStreamId;\n }\n\n public set streamId(value: string) {\n this.privStreamId = value;\n }\n\n public get audioOutputFormat(): AudioOutputFormatImpl {\n return this.privAudioOutputFormat;\n }\n\n public set audioOutputFormat(format: AudioOutputFormatImpl) {\n this.privAudioOutputFormat = format;\n }\n\n public get turnCompletionPromise(): Promise<boolean> {\n return this.privTurnDeferral.promise();\n }\n\n public get isSynthesisEnded(): boolean {\n return this.privIsSynthesisEnded;\n }\n\n public get isSynthesizing(): boolean {\n return this.privIsSynthesizing;\n }\n\n public get currentTextOffset(): number {\n return this.privTextOffset;\n }\n\n // The number of bytes received for current turn\n public get bytesReceived(): number {\n return this.privBytesReceived;\n }\n\n public get allReceivedAudio(): ArrayBuffer {\n if (!!this.privReceivedAudio) {\n return this.privReceivedAudio;\n }\n if (!this.privIsSynthesisEnded) {\n return null;\n }\n this.readAllAudioFromStream();\n return this.allReceivedAudio;\n }\n\n public get allReceivedAudioWithHeader(): ArrayBuffer {\n if (!!this.privReceivedAudioWithHeader) {\n return this.privReceivedAudioWithHeader;\n }\n if (!this.privIsSynthesisEnded) {\n return null;\n }\n if (this.audioOutputFormat.hasHeader) {\n this.privReceivedAudioWithHeader = SynthesisAdapterBase.addHeader(this.allReceivedAudio, this.audioOutputFormat);\n return this.allReceivedAudioWithHeader;\n } else {\n return this.allReceivedAudio;\n }\n }\n private privIsDisposed: boolean = false;\n private privAuthFetchEventId: string;\n private privIsSynthesizing: boolean = false;\n private privIsSynthesisEnded: boolean = false;\n private privBytesReceived: number = 0;\n private privRequestId: string;\n private privStreamId: string;\n private privTurnDeferral: Deferred<boolean>;\n private privAudioOutputFormat: AudioOutputFormatImpl;\n private privAudioOutputStream: PullAudioOutputStreamImpl;\n private privReceivedAudio: ArrayBuffer;\n private privReceivedAudioWithHeader: ArrayBuffer;\n private privTextOffset: number = 0;\n private privNextSearchTextIndex: number = 0;\n private privRawText: string;\n private privIsSSML: boolean;\n private privTurnAudioDestination: IAudioDestination;\n\n constructor() {\n this.privRequestId = createNoDashGuid();\n this.privTurnDeferral = new Deferred<boolean>();\n\n // We're not in a turn, so resolve.\n this.privTurnDeferral.resolve(true);\n }\n\n public startNewSynthesis(requestId: string, rawText: string, isSSML: boolean, audioDestination?: IAudioDestination): void {\n this.privIsSynthesisEnded = false;\n this.privIsSynthesizing = true;\n this.privRequestId = requestId;\n this.privRawText = rawText;\n this.privIsSSML = isSSML;\n this.privAudioOutputStream = new PullAudioOutputStreamImpl();\n this.privAudioOutputStream.format = this.privAudioOutputFormat;\n this.privReceivedAudio = null;\n this.privReceivedAudioWithHeader = null;\n this.privBytesReceived = 0;\n this.privTextOffset = 0;\n this.privNextSearchTextIndex = 0;\n if (audioDestination !== undefined) {\n this.privTurnAudioDestination = audioDestination;\n this.privTurnAudioDestination.format = this.privAudioOutputFormat;\n }\n this.onEvent(new SynthesisTriggeredEvent(this.requestId, undefined, audioDestination === undefined ? undefined : audioDestination.id()));\n }\n\n public onPreConnectionStart = (authFetchEventId: string, connectionId: string): void => {\n this.privAuthFetchEventId = authFetchEventId;\n this.onEvent(new ConnectingToSynthesisServiceEvent(this.privRequestId, this.privAuthFetchEventId));\n }\n\n public onAuthCompleted = (isError: boolean, error?: string): void => {\n if (isError) {\n this.onComplete();\n }\n }\n\n public onConnectionEstablishCompleted = (statusCode: number, reason?: string): void => {\n if (statusCode === 200) {\n this.onEvent(new SynthesisStartedEvent(this.requestId, this.privAuthFetchEventId));\n this.privBytesReceived = 0;\n return;\n } else if (statusCode === 403) {\n this.onComplete();\n }\n }\n\n public onServiceResponseMessage = (responseJson: string): void => {\n const response: ISynthesisResponse = JSON.parse(responseJson);\n this.streamId = response.audio.streamId;\n }\n\n public onServiceTurnEndResponse = (): void => {\n this.privTurnDeferral.resolve(true);\n this.onComplete();\n }\n\n public onServiceTurnStartResponse = (): void => {\n if (this.privTurnDeferral.state() === PromiseState.None) {\n // What? How are we starting a turn with another not done?\n this.privTurnDeferral.reject(\"Another turn started before current completed.\");\n }\n\n this.privTurnDeferral = new Deferred<boolean>();\n }\n\n public onAudioChunkReceived(data: ArrayBuffer): void {\n if (this.isSynthesizing) {\n this.privAudioOutputStream.write(data);\n this.privBytesReceived += data.byteLength;\n if (this.privTurnAudioDestination !== undefined) {\n this.privTurnAudioDestination.write(data);\n }\n }\n }\n\n public onWordBoundaryEvent(text: string): void {\n this.updateTextOffset(text);\n }\n\n public dispose = (error?: string): void => {\n if (!this.privIsDisposed) {\n // we should have completed by now. If we did not its an unknown error.\n this.privIsDisposed = true;\n }\n }\n\n public onStopSynthesizing(): void {\n this.onComplete();\n }\n\n protected onEvent = (event: SpeechSynthesisEvent): void => {\n Events.instance.onEvent(event);\n }\n\n private updateTextOffset(text: string): void {\n if (this.privTextOffset >= 0) {\n this.privTextOffset = this.privRawText.indexOf(text, this.privNextSearchTextIndex);\n if (this.privTextOffset >= 0) {\n this.privNextSearchTextIndex = this.privTextOffset + text.length;\n }\n if (this.privIsSSML) {\n if (this.privRawText.indexOf(\"<\", this.privTextOffset + 1) > this.privRawText.indexOf(\">\", this.privTextOffset + 1)) {\n this.updateTextOffset(text);\n }\n }\n }\n }\n\n private onComplete = (): void => {\n if (this.privIsSynthesizing) {\n this.privIsSynthesizing = false;\n this.privIsSynthesisEnded = true;\n this.privAudioOutputStream.close();\n if (this.privTurnAudioDestination !== undefined) {\n this.privTurnAudioDestination.close();\n this.privTurnAudioDestination = undefined;\n }\n }\n }\n\n private readAllAudioFromStream(): void {\n if (this.privIsSynthesisEnded) {\n this.privReceivedAudio = new ArrayBuffer(this.bytesReceived);\n try {\n this.privAudioOutputStream.read(this.privReceivedAudio);\n } catch (e) {\n this.privReceivedAudio = new ArrayBuffer(0);\n }\n }\n }\n}\n"]}