{"version":3,"sources":["src/sdk/Audio/AudioInputStream.ts"],"names":[],"mappings":"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","file":"AudioInputStream.d.ts","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT license.\n\nimport { createNoDashGuid } from \"../../../src/common/Guid\";\nimport {\n    connectivity,\n    ISpeechConfigAudioDevice,\n    type,\n} from \"../../common.speech/Exports\";\nimport {\n    AudioSourceEvent,\n    AudioSourceInitializingEvent,\n    AudioSourceReadyEvent,\n    AudioStreamNodeAttachedEvent,\n    AudioStreamNodeAttachingEvent,\n    AudioStreamNodeDetachedEvent,\n    ChunkedArrayBufferStream,\n    Events,\n    EventSource,\n    IAudioSource,\n    IAudioStreamNode,\n    IStreamChunk,\n    Promise,\n    PromiseHelper,\n    Stream,\n    StreamReader,\n} from \"../../common/Exports\";\nimport { AudioStreamFormat, PullAudioInputStreamCallback } from \"../Exports\";\nimport { AudioStreamFormatImpl } from \"./AudioStreamFormat\";\n\nexport const bufferSize: number = 4096;\n\n/**\n * Represents audio input stream used for custom audio input configurations.\n * @class AudioInputStream\n */\nexport abstract class AudioInputStream {\n\n    /**\n     * Creates and initializes an instance.\n     * @constructor\n     */\n    protected constructor() { }\n\n    /**\n     * Creates a memory backed PushAudioInputStream with the specified audio format.\n     * @member AudioInputStream.createPushStream\n     * @function\n     * @public\n     * @param {AudioStreamFormat} format - The audio data format in which audio will be\n     *        written to the push audio stream's write() method (currently only support 16 kHz 16bit mono PCM).\n     * @returns {PushAudioInputStream} The audio input stream being created.\n     */\n    public static createPushStream(format?: AudioStreamFormat): PushAudioInputStream {\n        return PushAudioInputStream.create(format);\n    }\n\n    /**\n     * Creates a PullAudioInputStream that delegates to the specified callback interface for read()\n     * and close() methods.\n     * @member AudioInputStream.createPullStream\n     * @function\n     * @public\n     * @param {PullAudioInputStreamCallback} callback - The custom audio input object, derived from\n     *        PullAudioInputStreamCallback\n     * @param {AudioStreamFormat} format - The audio data format in which audio will be returned from\n     *        the callback's read() method (currently only support 16 kHz 16bit mono PCM).\n     * @returns {PullAudioInputStream} The audio input stream being created.\n     */\n    public static createPullStream(callback: PullAudioInputStreamCallback, format?: AudioStreamFormat): PullAudioInputStream {\n        return PullAudioInputStream.create(callback, format);\n        // throw new Error(\"Oops\");\n    }\n\n    /**\n     * Explicitly frees any external resource attached to the object\n     * @member AudioInputStream.prototype.close\n     * @function\n     * @public\n     */\n    public abstract close(): void;\n}\n\n/**\n * Represents memory backed push audio input stream used for custom audio input configurations.\n * @class PushAudioInputStream\n */\n// tslint:disable-next-line:max-classes-per-file\nexport abstract class PushAudioInputStream extends AudioInputStream {\n\n    /**\n     * Creates a memory backed PushAudioInputStream with the specified audio format.\n     * @member PushAudioInputStream.create\n     * @function\n     * @public\n     * @param {AudioStreamFormat} format - The audio data format in which audio will be written to the\n     *        push audio stream's write() method (currently only support 16 kHz 16bit mono PCM).\n     * @returns {PushAudioInputStream} The push audio input stream being created.\n     */\n    public static create(format?: AudioStreamFormat): PushAudioInputStream {\n        return new PushAudioInputStreamImpl(bufferSize, format);\n    }\n\n    /**\n     * Writes the audio data specified by making an internal copy of the data.\n     * @member PushAudioInputStream.prototype.write\n     * @function\n     * @public\n     * @param {ArrayBuffer} dataBuffer - The audio buffer of which this function will make a copy.\n     */\n    public abstract write(dataBuffer: ArrayBuffer): void;\n\n    /**\n     * Closes the stream.\n     * @member PushAudioInputStream.prototype.close\n     * @function\n     * @public\n     */\n    public abstract close(): void;\n}\n\n/**\n * Represents memory backed push audio input stream used for custom audio input configurations.\n * @private\n * @class PushAudioInputStreamImpl\n */\n// tslint:disable-next-line:max-classes-per-file\nexport class PushAudioInputStreamImpl extends PushAudioInputStream implements IAudioSource {\n\n    private privFormat: AudioStreamFormatImpl;\n    private privId: string;\n    private privEvents: EventSource<AudioSourceEvent>;\n    private privStream: Stream<ArrayBuffer>;\n\n    /**\n     * Creates and initalizes an instance with the given values.\n     * @constructor\n     * @param {AudioStreamFormat} format - The audio stream format.\n     */\n    public constructor(chunkSize: number, format?: AudioStreamFormat) {\n        super();\n        if (format === undefined) {\n            this.privFormat = AudioStreamFormatImpl.getDefaultInputFormat();\n        } else {\n            this.privFormat = format as AudioStreamFormatImpl;\n        }\n        this.privEvents = new EventSource<AudioSourceEvent>();\n        this.privId = createNoDashGuid();\n        this.privStream = new ChunkedArrayBufferStream(chunkSize);\n    }\n\n    /**\n     * Format information for the audio\n     */\n    public get format(): AudioStreamFormat {\n        return this.privFormat;\n    }\n\n    /**\n     * Writes the audio data specified by making an internal copy of the data.\n     * @member PushAudioInputStreamImpl.prototype.write\n     * @function\n     * @public\n     * @param {ArrayBuffer} dataBuffer - The audio buffer of which this function will make a copy.\n     */\n    public write(dataBuffer: ArrayBuffer): void {\n        this.privStream.writeStreamChunk({\n            buffer: dataBuffer,\n            isEnd: false,\n            timeReceived: Date.now()\n        });\n    }\n\n    /**\n     * Closes the stream.\n     * @member PushAudioInputStreamImpl.prototype.close\n     * @function\n     * @public\n     */\n    public close(): void {\n        this.privStream.close();\n    }\n\n    public id(): string {\n        return this.privId;\n    }\n\n    public turnOn(): Promise<boolean> {\n        this.onEvent(new AudioSourceInitializingEvent(this.privId)); // no stream id\n        this.onEvent(new AudioSourceReadyEvent(this.privId));\n        return PromiseHelper.fromResult(true);\n    }\n\n    public attach(audioNodeId: string): Promise<IAudioStreamNode> {\n        this.onEvent(new AudioStreamNodeAttachingEvent(this.privId, audioNodeId));\n\n        return this.turnOn()\n            .onSuccessContinueWith<StreamReader<ArrayBuffer>>((_: boolean) => {\n                // For now we support a single parallel reader of the pushed stream.\n                // So we can simiply hand the stream to the recognizer and let it recognize.\n\n                return this.privStream.getReader();\n            })\n            .onSuccessContinueWith((streamReader: StreamReader<ArrayBuffer>) => {\n                this.onEvent(new AudioStreamNodeAttachedEvent(this.privId, audioNodeId));\n\n                return {\n                    detach: () => {\n                        streamReader.close();\n                        this.onEvent(new AudioStreamNodeDetachedEvent(this.privId, audioNodeId));\n                        this.turnOff();\n                    },\n                    id: () => {\n                        return audioNodeId;\n                    },\n                    read: () => {\n                        return streamReader.read();\n                    },\n                };\n            });\n    }\n\n    public detach(audioNodeId: string): void {\n        this.onEvent(new AudioStreamNodeDetachedEvent(this.privId, audioNodeId));\n    }\n\n    public turnOff(): Promise<boolean> {\n        return PromiseHelper.fromResult(false);\n    }\n\n    public get events(): EventSource<AudioSourceEvent> {\n        return this.privEvents;\n    }\n\n    public get deviceInfo(): Promise<ISpeechConfigAudioDevice> {\n        return PromiseHelper.fromResult({\n            bitspersample: this.privFormat.bitsPerSample,\n            channelcount: this.privFormat.channels,\n            connectivity: connectivity.Unknown,\n            manufacturer: \"Speech SDK\",\n            model: \"PushStream\",\n            samplerate: this.privFormat.samplesPerSec,\n            type: type.Stream,\n        });\n    }\n\n    private onEvent = (event: AudioSourceEvent): void => {\n        this.privEvents.onEvent(event);\n        Events.instance.onEvent(event);\n    }\n}\n\n/*\n * Represents audio input stream used for custom audio input configurations.\n * @class PullAudioInputStream\n */\n// tslint:disable-next-line:max-classes-per-file\nexport abstract class PullAudioInputStream extends AudioInputStream {\n    /**\n     * Creates and initializes and instance.\n     * @constructor\n     */\n    protected constructor() { super(); }\n\n    /**\n     * Creates a PullAudioInputStream that delegates to the specified callback interface for\n     * read() and close() methods, using the default format (16 kHz 16bit mono PCM).\n     * @member PullAudioInputStream.create\n     * @function\n     * @public\n     * @param {PullAudioInputStreamCallback} callback - The custom audio input object,\n     *        derived from PullAudioInputStreamCustomCallback\n     * @param {AudioStreamFormat} format - The audio data format in which audio will be\n     *        returned from the callback's read() method (currently only support 16 kHz 16bit mono PCM).\n     * @returns {PullAudioInputStream} The push audio input stream being created.\n     */\n    public static create(callback: PullAudioInputStreamCallback, format?: AudioStreamFormat): PullAudioInputStream {\n        return new PullAudioInputStreamImpl(callback, format as AudioStreamFormatImpl);\n    }\n\n    /**\n     * Explicitly frees any external resource attached to the object\n     * @member PullAudioInputStream.prototype.close\n     * @function\n     * @public\n     */\n    public abstract close(): void;\n\n}\n\n/**\n * Represents audio input stream used for custom audio input configurations.\n * @private\n * @class PullAudioInputStreamImpl\n */\n// tslint:disable-next-line:max-classes-per-file\nexport class PullAudioInputStreamImpl extends PullAudioInputStream implements IAudioSource {\n\n    private privCallback: PullAudioInputStreamCallback;\n    private privFormat: AudioStreamFormatImpl;\n    private privId: string;\n    private privEvents: EventSource<AudioSourceEvent>;\n    private privIsClosed: boolean;\n\n    /**\n     * Creates a PullAudioInputStream that delegates to the specified callback interface for\n     * read() and close() methods, using the default format (16 kHz 16bit mono PCM).\n     * @constructor\n     * @param {PullAudioInputStreamCallback} callback - The custom audio input object,\n     *        derived from PullAudioInputStreamCustomCallback\n     * @param {AudioStreamFormat} format - The audio data format in which audio will be\n     *        returned from the callback's read() method (currently only support 16 kHz 16bit mono PCM).\n     */\n    public constructor(callback: PullAudioInputStreamCallback, format?: AudioStreamFormatImpl) {\n        super();\n        if (undefined === format) {\n            this.privFormat = AudioStreamFormat.getDefaultInputFormat() as AudioStreamFormatImpl;\n        } else {\n            this.privFormat = format;\n        }\n        this.privEvents = new EventSource<AudioSourceEvent>();\n        this.privId = createNoDashGuid();\n        this.privCallback = callback;\n        this.privIsClosed = false;\n    }\n\n    /**\n     * Format information for the audio\n     */\n    public get format(): AudioStreamFormat {\n        return this.privFormat;\n    }\n\n    /**\n     * Closes the stream.\n     * @member PullAudioInputStreamImpl.prototype.close\n     * @function\n     * @public\n     */\n    public close(): void {\n        this.privIsClosed = true;\n        this.privCallback.close();\n    }\n\n    public id(): string {\n        return this.privId;\n    }\n\n    public turnOn(): Promise<boolean> {\n        this.onEvent(new AudioSourceInitializingEvent(this.privId)); // no stream id\n        this.onEvent(new AudioSourceReadyEvent(this.privId));\n        return PromiseHelper.fromResult(true);\n    }\n\n    public attach(audioNodeId: string): Promise<IAudioStreamNode> {\n        this.onEvent(new AudioStreamNodeAttachingEvent(this.privId, audioNodeId));\n\n        return this.turnOn()\n            .onSuccessContinueWith((result: boolean) => {\n                this.onEvent(new AudioStreamNodeAttachedEvent(this.privId, audioNodeId));\n\n                return {\n                    detach: () => {\n                        this.privCallback.close();\n                        this.onEvent(new AudioStreamNodeDetachedEvent(this.privId, audioNodeId));\n                        this.turnOff();\n                    },\n                    id: () => {\n                        return audioNodeId;\n                    },\n                    read: (): Promise<IStreamChunk<ArrayBuffer>> => {\n                        let totalBytes: number = 0;\n                        let transmitBuff: ArrayBuffer;\n\n                        // Until we have the minimum number of bytes to send in a transmission, keep asking for more.\n                        while (totalBytes < bufferSize) {\n                            // Sizing the read buffer to the delta between the perfect size and what's left means we won't ever get too much\n                            // data back.\n                            const readBuff: ArrayBuffer = new ArrayBuffer(bufferSize - totalBytes);\n                            const pulledBytes: number = this.privCallback.read(readBuff);\n\n                            // If there is no return buffer yet defined, set the return buffer to the that was just populated.\n                            // This was, if we have enough data there's no copy penalty, but if we don't we have a buffer that's the\n                            // preferred size allocated.\n                            if (undefined === transmitBuff) {\n                                transmitBuff = readBuff;\n                            } else {\n                                // Not the first bite at the apple, so fill the return buffer with the data we got back.\n                                const intView: Int8Array = new Int8Array(transmitBuff);\n                                intView.set(new Int8Array(readBuff), totalBytes);\n                            }\n\n                            // If there are no bytes to read, just break out and be done.\n                            if (0 === pulledBytes) {\n                                break;\n                            }\n\n                            totalBytes += pulledBytes;\n                        }\n\n                        return PromiseHelper.fromResult<IStreamChunk<ArrayBuffer>>({\n                            buffer: transmitBuff.slice(0, totalBytes),\n                            isEnd: this.privIsClosed || totalBytes === 0,\n                            timeReceived: Date.now(),\n                        });\n                    },\n                };\n            });\n    }\n\n    public detach(audioNodeId: string): void {\n        this.onEvent(new AudioStreamNodeDetachedEvent(this.privId, audioNodeId));\n    }\n\n    public turnOff(): Promise<boolean> {\n        return PromiseHelper.fromResult(false);\n    }\n\n    public get events(): EventSource<AudioSourceEvent> {\n        return this.privEvents;\n    }\n\n    public get deviceInfo(): Promise<ISpeechConfigAudioDevice> {\n        return PromiseHelper.fromResult({\n            bitspersample: this.privFormat.bitsPerSample,\n            channelcount: this.privFormat.channels,\n            connectivity: connectivity.Unknown,\n            manufacturer: \"Speech SDK\",\n            model: \"PullStream\",\n            samplerate: this.privFormat.samplesPerSec,\n            type: type.Stream,\n        });\n    }\n\n    private onEvent = (event: AudioSourceEvent): void => {\n        this.privEvents.onEvent(event);\n        Events.instance.onEvent(event);\n    }\n}\n"]}