@speechly/browser-client
Advanced tools
Comparing version 1.0.14 to 1.0.15
@@ -22,2 +22,13 @@ | ||
* | ||
* This method will be called by the Client as part of the initialisation process. | ||
* | ||
* @param apiUrl - url. | ||
* @param authToken - authentication token. | ||
* @param targetSampleRate - target sample rate of audio. | ||
* @param debug - debug flag. | ||
*/ | ||
initialize(apiUrl: string, authToken: string, targetSampleRate: number, debug: boolean): Promise<void>; | ||
/** | ||
* Initialises the client. | ||
* | ||
* This should prepare websocket to be used (set source sample rate). | ||
@@ -28,3 +39,3 @@ * This method will be called by the Client as part of the initialisation process. | ||
*/ | ||
initialize(sourceSampleRate: number): Promise<void>; | ||
setSourceSampleRate(sourceSampleRate: number): Promise<void>; | ||
/** | ||
@@ -97,2 +108,4 @@ * Closes the client. | ||
private initializeMicrophonePromise?; | ||
private readonly initializeApiClientPromise; | ||
private resolveInitialization?; | ||
private resolveStopContext?; | ||
@@ -99,0 +112,0 @@ private readonly deviceId; |
{ | ||
"name": "@speechly/browser-client", | ||
"version": "1.0.14", | ||
"version": "1.0.15", | ||
"description": "Browser client for Speechly API", | ||
@@ -5,0 +5,0 @@ "private": false, |
@@ -31,2 +31,4 @@ import { ClientOptions, StateChangeCallback, SegmentChangeCallback, TentativeTranscriptCallback, TranscriptCallback, TentativeEntitiesCallback, EntityCallback, IntentCallback } from './types'; | ||
private initializeMicrophonePromise?; | ||
private readonly initializeApiClientPromise; | ||
private resolveInitialization?; | ||
private resolveStopContext?; | ||
@@ -33,0 +35,0 @@ private readonly deviceId; |
@@ -162,2 +162,5 @@ "use strict"; | ||
// 2. Fetch auth token. It doesn't matter if it's not present. | ||
this.initializeApiClientPromise = new Promise(resolve => { | ||
this.resolveInitialization = resolve; | ||
}); | ||
if (storedToken == null || !token_1.validateToken(storedToken, this.projectId, this.appId, this.deviceId)) { | ||
@@ -197,9 +200,11 @@ token_1.fetchToken(this.loginUrl, this.projectId, this.appId, this.deviceId) | ||
connect(apiUrl) { | ||
this.apiClient.postMessage({ | ||
type: 'INIT', | ||
apiUrl: apiUrl, | ||
authToken: this.authToken, | ||
targetSampleRate: this.sampleRate, | ||
debug: this.debug, | ||
}); | ||
if (this.authToken != null) { | ||
this.apiClient.initialize(apiUrl, this.authToken, this.sampleRate, this.debug).then(() => { | ||
if (this.resolveInitialization != null) { | ||
this.resolveInitialization(); | ||
} | ||
}).catch(err => { | ||
throw err; | ||
}); | ||
} | ||
} | ||
@@ -217,2 +222,3 @@ /** | ||
return __awaiter(this, void 0, void 0, function* () { | ||
yield this.initializeApiClientPromise; | ||
if (this.state !== types_1.ClientState.Disconnected) { | ||
@@ -263,3 +269,3 @@ throw Error('Cannot initialize client - client is not in Disconnected state'); | ||
// 3. Initialise websocket. | ||
yield this.apiClient.initialize(this.audioContext.sampleRate); | ||
yield this.apiClient.setSourceSampleRate(this.audioContext.sampleRate); | ||
this.initializeMicrophonePromise = this.microphone.initialize(this.audioContext, opts); | ||
@@ -266,0 +272,0 @@ yield this.initializeMicrophonePromise; |
@@ -154,2 +154,13 @@ /** | ||
* | ||
* This method will be called by the Client as part of the initialisation process. | ||
* | ||
* @param apiUrl - url. | ||
* @param authToken - authentication token. | ||
* @param targetSampleRate - target sample rate of audio. | ||
* @param debug - debug flag. | ||
*/ | ||
initialize(apiUrl: string, authToken: string, targetSampleRate: number, debug: boolean): Promise<void>; | ||
/** | ||
* Initialises the client. | ||
* | ||
* This should prepare websocket to be used (set source sample rate). | ||
@@ -160,3 +171,3 @@ * This method will be called by the Client as part of the initialisation process. | ||
*/ | ||
initialize(sourceSampleRate: number): Promise<void>; | ||
setSourceSampleRate(sourceSampleRate: number): Promise<void>; | ||
/** | ||
@@ -163,0 +174,0 @@ * Closes the client. |
@@ -5,2 +5,3 @@ import { APIClient, ResponseCallback, CloseCallback } from './types'; | ||
private resolveInitialization?; | ||
private resolveSourceSampleRateSet?; | ||
private startCbs; | ||
@@ -13,3 +14,4 @@ private stopCbs; | ||
constructor(); | ||
initialize(sourceSampleRate: number): Promise<void>; | ||
initialize(apiUrl: string, authToken: string, targetSampleRate: number, debug: boolean): Promise<void>; | ||
setSourceSampleRate(sourceSampleRate: number): Promise<void>; | ||
close(): Promise<void>; | ||
@@ -16,0 +18,0 @@ startContext(appId?: string): Promise<string>; |
@@ -27,4 +27,2 @@ "use strict"; | ||
case types_1.WebsocketResponseType.Opened: | ||
break; | ||
case types_1.WebsocketResponseType.SourceSampleRateSetSuccess: | ||
if (this.resolveInitialization != null) { | ||
@@ -34,2 +32,7 @@ this.resolveInitialization(); | ||
break; | ||
case types_1.WebsocketResponseType.SourceSampleRateSetSuccess: | ||
if (this.resolveSourceSampleRateSet != null) { | ||
this.resolveSourceSampleRateSet(); | ||
} | ||
break; | ||
case types_1.WebsocketResponseType.Started: | ||
@@ -72,5 +75,19 @@ this.startCbs.forEach(cb => { | ||
} | ||
initialize(sourceSampleRate) { | ||
initialize(apiUrl, authToken, targetSampleRate, debug) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this.worker.postMessage({ | ||
type: 'INIT', | ||
apiUrl, | ||
authToken, | ||
targetSampleRate, | ||
debug, | ||
}); | ||
return new Promise(resolve => { | ||
this.resolveInitialization = resolve; | ||
}); | ||
}); | ||
} | ||
setSourceSampleRate(sourceSampleRate) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this.worker.postMessage({ | ||
type: 'SET_SOURSE_SAMPLE_RATE', | ||
@@ -80,3 +97,3 @@ sourceSampleRate, | ||
return new Promise(resolve => { | ||
this.resolveInitialization = resolve; | ||
this.resolveSourceSampleRateSet = resolve; | ||
}); | ||
@@ -83,0 +100,0 @@ }); |
@@ -1,2 +0,2 @@ | ||
declare const _default: "/**\n * Known WebSocket response types.\n * @public\n */\nvar WebsocketResponseType;\n(function (WebsocketResponseType) {\n WebsocketResponseType[\"Opened\"] = \"WEBSOCKET_OPEN\";\n WebsocketResponseType[\"SourceSampleRateSetSuccess\"] = \"SOURSE_SAMPLE_RATE_SET_SUCCESS\";\n WebsocketResponseType[\"Started\"] = \"started\";\n WebsocketResponseType[\"Stopped\"] = \"stopped\";\n})(WebsocketResponseType || (WebsocketResponseType = {}));\nvar CONTROL = {\n WRITE_INDEX: 0,\n FRAMES_AVAILABLE: 1,\n LOCK: 2\n};\nvar WebsocketClient = /** @class */ (function () {\n function WebsocketClient(ctx) {\n var _this = this;\n this.isContextStarted = false;\n this.isStartContextConfirmed = false;\n this.shouldResendLastFramesSent = false;\n this.buffer = new Float32Array(0);\n this.lastFramesSent = new Int16Array(0); // to re-send after switch context\n this.debug = false;\n this.initialized = false;\n this.onWebsocketClose = function (event) {\n _this.websocket = undefined;\n _this.connect(0);\n };\n this.onWebsocketOpen = function (_event) {\n if (_this.debug) {\n console.log('[SpeechlyClient]', 'websocket opened');\n }\n _this.workerCtx.postMessage({ type: 'WEBSOCKET_OPEN' });\n };\n this.onWebsocketError = function (_event) {\n if (_this.debug) {\n console.log('[SpeechlyClient]', 'websocket error');\n }\n _this.closeWebsocket();\n };\n this.onWebsocketMessage = function (event) {\n var response;\n try {\n response = JSON.parse(event.data);\n }\n catch (e) {\n console.error('[SpeechlyClient] Error parsing response from the server:', e);\n return;\n }\n if (response.type === WebsocketResponseType.Started) {\n _this.isStartContextConfirmed = true;\n if (_this.shouldResendLastFramesSent) {\n _this.resendLastFrames();\n _this.shouldResendLastFramesSent = false;\n }\n }\n _this.workerCtx.postMessage(response);\n };\n this.workerCtx = ctx;\n }\n WebsocketClient.prototype.init = function (apiUrl, authToken, targetSampleRate, debug) {\n if (this.initialized) {\n console.log('[SpeechlyClient]', 'already initialized');\n return;\n }\n this.debug = debug;\n if (this.debug) {\n console.log('[SpeechlyClient]', 'initialize worker');\n }\n this.apiUrl = apiUrl;\n this.authToken = authToken;\n this.targetSampleRate = targetSampleRate;\n this.initialized = true;\n this.connect(0);\n };\n WebsocketClient.prototype.setSourceSampleRate = function (sourceSampleRate) {\n this.sourceSampleRate = sourceSampleRate;\n this.resampleRatio = this.sourceSampleRate / this.targetSampleRate;\n if (this.debug) {\n console.log('[SpeechlyClient]', 'resampleRatio', this.resampleRatio);\n }\n if (this.resampleRatio > 1) {\n this.filter = generateFilter(this.sourceSampleRate, this.targetSampleRate, 127);\n }\n this.workerCtx.postMessage({ type: 'SOURSE_SAMPLE_RATE_SET_SUCCESS' });\n if (isNaN(this.resampleRatio)) {\n throw Error('resampleRatio is NaN');\n }\n };\n WebsocketClient.prototype.setSharedArrayBuffers = function (controlSAB, dataSAB) {\n this.controlSAB = new Int32Array(controlSAB);\n this.dataSAB = new Float32Array(dataSAB);\n var audioHandleInterval = this.dataSAB.length / 32; // ms\n if (this.debug) {\n console.log('[SpeechlyClient]', 'Audio handle interval', audioHandleInterval, 'ms');\n }\n setInterval(this.sendAudioFromSAB.bind(this), audioHandleInterval);\n };\n WebsocketClient.prototype.connect = function (timeout) {\n if (timeout === void 0) { timeout = 1000; }\n if (this.debug) {\n console.log('[SpeechlyClient]', 'connect in ', timeout / 1000, 'sec');\n }\n setTimeout(this.initializeWebsocket.bind(this), timeout);\n };\n WebsocketClient.prototype.initializeWebsocket = function () {\n if (this.debug) {\n console.log('[SpeechlyClient]', 'connecting to ', this.apiUrl);\n }\n this.websocket = new WebSocket(this.apiUrl, this.authToken);\n this.websocket.addEventListener('open', this.onWebsocketOpen);\n this.websocket.addEventListener('message', this.onWebsocketMessage);\n this.websocket.addEventListener('error', this.onWebsocketError);\n this.websocket.addEventListener('close', this.onWebsocketClose);\n };\n WebsocketClient.prototype.isOpen = function () {\n return this.websocket !== undefined && this.websocket.readyState === this.websocket.OPEN;\n };\n WebsocketClient.prototype.resendLastFrames = function () {\n if (!this.isOpen()) {\n return Error('Cannot resend data through inactive websocket');\n }\n if (this.lastFramesSent.length > 0) {\n this.websocket.send(this.lastFramesSent);\n this.lastFramesSent = new Int16Array(0);\n }\n };\n WebsocketClient.prototype.sendAudio = function (audioChunk) {\n if (!this.isContextStarted) {\n return;\n }\n if (!this.isOpen()) {\n return Error('Cannot send data through inactive websocket');\n }\n if (audioChunk.length > 0) {\n if (this.resampleRatio > 1) {\n // Downsampling\n this.websocket.send(this.downsample(audioChunk));\n }\n else {\n this.websocket.send(float32ToInt16(audioChunk));\n }\n }\n };\n WebsocketClient.prototype.sendAudioFromSAB = function () {\n if (!this.isContextStarted) {\n this.controlSAB[CONTROL.FRAMES_AVAILABLE] = 0;\n this.controlSAB[CONTROL.WRITE_INDEX] = 0;\n return;\n }\n if (this.controlSAB == undefined) {\n return;\n }\n var framesAvailable = this.controlSAB[CONTROL.FRAMES_AVAILABLE];\n var lock = this.controlSAB[CONTROL.LOCK];\n if (lock == 0 && framesAvailable > 0) {\n var data = this.dataSAB.subarray(0, framesAvailable);\n this.controlSAB[CONTROL.FRAMES_AVAILABLE] = 0;\n this.controlSAB[CONTROL.WRITE_INDEX] = 0;\n if (data.length > 0) {\n var frames_1;\n if (this.resampleRatio > 1) {\n frames_1 = this.downsample(data);\n }\n else {\n frames_1 = float32ToInt16(data);\n }\n this.websocket.send(frames_1);\n // 16000 per second, 1000 in 100 ms\n // save last 250 ms\n if (this.lastFramesSent.length > 1024 * 4) {\n this.lastFramesSent = frames_1;\n }\n else {\n var concat = new Int16Array(this.lastFramesSent.length + frames_1.length);\n concat.set(this.lastFramesSent);\n concat.set(frames_1, this.lastFramesSent.length);\n this.lastFramesSent = concat;\n }\n }\n }\n };\n WebsocketClient.prototype.startContext = function (appId) {\n if (!this.isOpen()) {\n throw Error('Cant start context: websocket is inactive');\n }\n if (this.isContextStarted) {\n console.log('Cant start context: it has been already started');\n return;\n }\n this.isContextStarted = true;\n this.isStartContextConfirmed = false;\n if (appId !== undefined) {\n this.websocket.send(JSON.stringify({ event: 'start', appId: appId }));\n }\n else {\n this.websocket.send(JSON.stringify({ event: 'start' }));\n }\n };\n WebsocketClient.prototype.stopContext = function () {\n if (this.websocket == undefined) {\n throw Error('Cant start context: websocket is undefined');\n }\n if (!this.isContextStarted) {\n console.log('Cant stop context: it is not started');\n return;\n }\n this.isContextStarted = false;\n this.isStartContextConfirmed = false;\n var StopEventJSON = JSON.stringify({ event: 'stop' });\n this.websocket.send(StopEventJSON);\n };\n WebsocketClient.prototype.switchContext = function (newAppId) {\n if (this.websocket == undefined) {\n throw Error('Cant switch context: websocket is undefined');\n }\n if (!this.isContextStarted) {\n console.log('Cant switch context: it is not started');\n return;\n }\n if (newAppId == undefined) {\n console.log('Cant switch context: new app id is undefined');\n return;\n }\n this.isStartContextConfirmed = false;\n var StopEventJSON = JSON.stringify({ event: 'stop' });\n this.websocket.send(StopEventJSON);\n this.shouldResendLastFramesSent = true;\n this.websocket.send(JSON.stringify({ event: 'start', appId: newAppId }));\n };\n WebsocketClient.prototype.closeWebsocket = function () {\n if (this.websocket == null) {\n throw Error('Websocket is not open');\n }\n this.websocket.removeEventListener('open', this.onWebsocketOpen);\n this.websocket.removeEventListener('message', this.onWebsocketMessage);\n this.websocket.removeEventListener('error', this.onWebsocketError);\n this.websocket.removeEventListener('close', this.onWebsocketClose);\n this.websocket.close();\n };\n WebsocketClient.prototype.downsample = function (input) {\n var inputBuffer = new Float32Array(this.buffer.length + input.length);\n inputBuffer.set(this.buffer, 0);\n inputBuffer.set(input, this.buffer.length);\n var outputLength = Math.ceil((inputBuffer.length - this.filter.length) / this.resampleRatio);\n var outputBuffer = new Int16Array(outputLength);\n for (var i = 0; i < outputLength; i++) {\n var offset = Math.round(this.resampleRatio * i);\n var val = 0.0;\n for (var j = 0; j < this.filter.length; j++) {\n val += inputBuffer[offset + j] * this.filter[j];\n }\n outputBuffer[i] = val * (val < 0 ? 0x8000 : 0x7fff);\n }\n var remainingOffset = Math.round(this.resampleRatio * outputLength);\n if (remainingOffset < inputBuffer.length) {\n this.buffer = inputBuffer.subarray(remainingOffset);\n }\n else {\n this.buffer = new Float32Array(0);\n }\n return outputBuffer;\n };\n return WebsocketClient;\n}());\nvar ctx = self;\nvar websocketClient = new WebsocketClient(ctx);\nctx.onmessage = function (e) {\n switch (e.data.type) {\n case 'INIT':\n websocketClient.init(e.data.apiUrl, e.data.authToken, e.data.targetSampleRate, e.data.debug);\n break;\n case 'SET_SOURSE_SAMPLE_RATE':\n websocketClient.setSourceSampleRate(e.data.sourceSampleRate);\n break;\n case 'SET_SHARED_ARRAY_BUFFERS':\n websocketClient.setSharedArrayBuffers(e.data.controlSAB, e.data.dataSAB);\n break;\n case 'CLOSE':\n websocketClient.closeWebsocket();\n break;\n case 'START_CONTEXT':\n websocketClient.startContext(e.data.appId);\n break;\n case 'SWITCH_CONTEXT':\n websocketClient.switchContext(e.data.appId);\n break;\n case 'STOP_CONTEXT':\n websocketClient.stopContext();\n break;\n case 'AUDIO':\n websocketClient.sendAudio(e.data.payload);\n break;\n default:\n console.log('WORKER', e);\n }\n};\nfunction float32ToInt16(buffer) {\n var buf = new Int16Array(buffer.length);\n for (var l = 0; l < buffer.length; l++) {\n buf[l] = buffer[l] * (buffer[l] < 0 ? 0x8000 : 0x7fff);\n }\n return buf;\n}\nfunction generateFilter(sourceSampleRate, targetSampleRate, length) {\n if (length % 2 === 0) {\n throw Error('Filter length must be odd');\n }\n var cutoff = targetSampleRate / 2;\n var filter = new Float32Array(length);\n var sum = 0;\n for (var i = 0; i < length; i++) {\n var x = sinc(((2 * cutoff) / sourceSampleRate) * (i - (length - 1) / 2));\n sum += x;\n filter[i] = x;\n }\n for (var i = 0; i < length; i++) {\n filter[i] = filter[i] / sum;\n }\n return filter;\n}\nfunction sinc(x) {\n if (x === 0.0) {\n return 1.0;\n }\n var piX = Math.PI * x;\n return Math.sin(piX) / piX;\n}\n"; | ||
declare const _default: "/**\n * Known WebSocket response types.\n * @public\n */\nvar WebsocketResponseType;\n(function (WebsocketResponseType) {\n WebsocketResponseType[\"Opened\"] = \"WEBSOCKET_OPEN\";\n WebsocketResponseType[\"SourceSampleRateSetSuccess\"] = \"SOURSE_SAMPLE_RATE_SET_SUCCESS\";\n WebsocketResponseType[\"Started\"] = \"started\";\n WebsocketResponseType[\"Stopped\"] = \"stopped\";\n})(WebsocketResponseType || (WebsocketResponseType = {}));\nvar CONTROL = {\n WRITE_INDEX: 0,\n FRAMES_AVAILABLE: 1,\n LOCK: 2\n};\nvar WebsocketClient = /** @class */ (function () {\n function WebsocketClient(ctx) {\n var _this = this;\n this.isContextStarted = false;\n this.isStartContextConfirmed = false;\n this.shouldResendLastFramesSent = false;\n this.buffer = new Float32Array(0);\n this.lastFramesSent = new Int16Array(0); // to re-send after switch context\n this.debug = false;\n this.initialized = false;\n this.onWebsocketClose = function (event) {\n _this.websocket = undefined;\n _this.connect(0);\n };\n this.onWebsocketOpen = function (_event) {\n if (_this.debug) {\n console.log('[SpeechlyClient]', 'websocket opened');\n }\n _this.workerCtx.postMessage({ type: 'WEBSOCKET_OPEN' });\n };\n this.onWebsocketError = function (_event) {\n if (_this.debug) {\n console.log('[SpeechlyClient]', 'websocket error');\n }\n _this.closeWebsocket();\n };\n this.onWebsocketMessage = function (event) {\n var response;\n try {\n response = JSON.parse(event.data);\n }\n catch (e) {\n console.error('[SpeechlyClient] Error parsing response from the server:', e);\n return;\n }\n if (response.type === WebsocketResponseType.Started) {\n _this.isStartContextConfirmed = true;\n if (_this.shouldResendLastFramesSent) {\n _this.resendLastFrames();\n _this.shouldResendLastFramesSent = false;\n }\n }\n _this.workerCtx.postMessage(response);\n };\n this.workerCtx = ctx;\n }\n WebsocketClient.prototype.init = function (apiUrl, authToken, targetSampleRate, debug) {\n if (this.initialized) {\n console.log('[SpeechlyClient]', 'already initialized');\n return;\n }\n this.debug = debug;\n if (this.debug) {\n console.log('[SpeechlyClient]', 'initialize worker');\n }\n this.apiUrl = apiUrl;\n this.authToken = authToken;\n this.targetSampleRate = targetSampleRate;\n this.initialized = true;\n this.connect(0);\n };\n WebsocketClient.prototype.setSourceSampleRate = function (sourceSampleRate) {\n this.sourceSampleRate = sourceSampleRate;\n this.resampleRatio = this.sourceSampleRate / this.targetSampleRate;\n if (this.debug) {\n console.log('[SpeechlyClient]', 'resampleRatio', this.resampleRatio);\n }\n if (this.resampleRatio > 1) {\n this.filter = generateFilter(this.sourceSampleRate, this.targetSampleRate, 127);\n }\n this.workerCtx.postMessage({ type: 'SOURSE_SAMPLE_RATE_SET_SUCCESS' });\n if (isNaN(this.resampleRatio)) {\n throw Error(\"resampleRatio is NaN source rate is \" + this.sourceSampleRate + \" and target rate is \" + this.targetSampleRate);\n }\n };\n WebsocketClient.prototype.setSharedArrayBuffers = function (controlSAB, dataSAB) {\n this.controlSAB = new Int32Array(controlSAB);\n this.dataSAB = new Float32Array(dataSAB);\n var audioHandleInterval = this.dataSAB.length / 32; // ms\n if (this.debug) {\n console.log('[SpeechlyClient]', 'Audio handle interval', audioHandleInterval, 'ms');\n }\n setInterval(this.sendAudioFromSAB.bind(this), audioHandleInterval);\n };\n WebsocketClient.prototype.connect = function (timeout) {\n if (timeout === void 0) { timeout = 1000; }\n if (this.debug) {\n console.log('[SpeechlyClient]', 'connect in ', timeout / 1000, 'sec');\n }\n setTimeout(this.initializeWebsocket.bind(this), timeout);\n };\n WebsocketClient.prototype.initializeWebsocket = function () {\n if (this.debug) {\n console.log('[SpeechlyClient]', 'connecting to ', this.apiUrl);\n }\n this.websocket = new WebSocket(this.apiUrl, this.authToken);\n this.websocket.addEventListener('open', this.onWebsocketOpen);\n this.websocket.addEventListener('message', this.onWebsocketMessage);\n this.websocket.addEventListener('error', this.onWebsocketError);\n this.websocket.addEventListener('close', this.onWebsocketClose);\n };\n WebsocketClient.prototype.isOpen = function () {\n return this.websocket !== undefined && this.websocket.readyState === this.websocket.OPEN;\n };\n WebsocketClient.prototype.resendLastFrames = function () {\n if (!this.isOpen()) {\n return Error('Cannot resend data through inactive websocket');\n }\n if (this.lastFramesSent.length > 0) {\n this.websocket.send(this.lastFramesSent);\n this.lastFramesSent = new Int16Array(0);\n }\n };\n WebsocketClient.prototype.sendAudio = function (audioChunk) {\n if (!this.isContextStarted) {\n return;\n }\n if (!this.isOpen()) {\n return Error('Cannot send data through inactive websocket');\n }\n if (audioChunk.length > 0) {\n if (this.resampleRatio > 1) {\n // Downsampling\n this.websocket.send(this.downsample(audioChunk));\n }\n else {\n this.websocket.send(float32ToInt16(audioChunk));\n }\n }\n };\n WebsocketClient.prototype.sendAudioFromSAB = function () {\n if (!this.isContextStarted) {\n this.controlSAB[CONTROL.FRAMES_AVAILABLE] = 0;\n this.controlSAB[CONTROL.WRITE_INDEX] = 0;\n return;\n }\n if (this.controlSAB == undefined) {\n return;\n }\n var framesAvailable = this.controlSAB[CONTROL.FRAMES_AVAILABLE];\n var lock = this.controlSAB[CONTROL.LOCK];\n if (lock == 0 && framesAvailable > 0) {\n var data = this.dataSAB.subarray(0, framesAvailable);\n this.controlSAB[CONTROL.FRAMES_AVAILABLE] = 0;\n this.controlSAB[CONTROL.WRITE_INDEX] = 0;\n if (data.length > 0) {\n var frames_1;\n if (this.resampleRatio > 1) {\n frames_1 = this.downsample(data);\n }\n else {\n frames_1 = float32ToInt16(data);\n }\n this.websocket.send(frames_1);\n // 16000 per second, 1000 in 100 ms\n // save last 250 ms\n if (this.lastFramesSent.length > 1024 * 4) {\n this.lastFramesSent = frames_1;\n }\n else {\n var concat = new Int16Array(this.lastFramesSent.length + frames_1.length);\n concat.set(this.lastFramesSent);\n concat.set(frames_1, this.lastFramesSent.length);\n this.lastFramesSent = concat;\n }\n }\n }\n };\n WebsocketClient.prototype.startContext = function (appId) {\n if (!this.isOpen()) {\n throw Error('Cant start context: websocket is inactive');\n }\n if (this.isContextStarted) {\n console.log('Cant start context: it has been already started');\n return;\n }\n this.isContextStarted = true;\n this.isStartContextConfirmed = false;\n if (appId !== undefined) {\n this.websocket.send(JSON.stringify({ event: 'start', appId: appId }));\n }\n else {\n this.websocket.send(JSON.stringify({ event: 'start' }));\n }\n };\n WebsocketClient.prototype.stopContext = function () {\n if (this.websocket == undefined) {\n throw Error('Cant start context: websocket is undefined');\n }\n if (!this.isContextStarted) {\n console.log('Cant stop context: it is not started');\n return;\n }\n this.isContextStarted = false;\n this.isStartContextConfirmed = false;\n var StopEventJSON = JSON.stringify({ event: 'stop' });\n this.websocket.send(StopEventJSON);\n };\n WebsocketClient.prototype.switchContext = function (newAppId) {\n if (this.websocket == undefined) {\n throw Error('Cant switch context: websocket is undefined');\n }\n if (!this.isContextStarted) {\n console.log('Cant switch context: it is not started');\n return;\n }\n if (newAppId == undefined) {\n console.log('Cant switch context: new app id is undefined');\n return;\n }\n this.isStartContextConfirmed = false;\n var StopEventJSON = JSON.stringify({ event: 'stop' });\n this.websocket.send(StopEventJSON);\n this.shouldResendLastFramesSent = true;\n this.websocket.send(JSON.stringify({ event: 'start', appId: newAppId }));\n };\n WebsocketClient.prototype.closeWebsocket = function () {\n if (this.websocket == null) {\n throw Error('Websocket is not open');\n }\n this.websocket.removeEventListener('open', this.onWebsocketOpen);\n this.websocket.removeEventListener('message', this.onWebsocketMessage);\n this.websocket.removeEventListener('error', this.onWebsocketError);\n this.websocket.removeEventListener('close', this.onWebsocketClose);\n this.websocket.close();\n };\n WebsocketClient.prototype.downsample = function (input) {\n var inputBuffer = new Float32Array(this.buffer.length + input.length);\n inputBuffer.set(this.buffer, 0);\n inputBuffer.set(input, this.buffer.length);\n var outputLength = Math.ceil((inputBuffer.length - this.filter.length) / this.resampleRatio);\n var outputBuffer = new Int16Array(outputLength);\n for (var i = 0; i < outputLength; i++) {\n var offset = Math.round(this.resampleRatio * i);\n var val = 0.0;\n for (var j = 0; j < this.filter.length; j++) {\n val += inputBuffer[offset + j] * this.filter[j];\n }\n outputBuffer[i] = val * (val < 0 ? 0x8000 : 0x7fff);\n }\n var remainingOffset = Math.round(this.resampleRatio * outputLength);\n if (remainingOffset < inputBuffer.length) {\n this.buffer = inputBuffer.subarray(remainingOffset);\n }\n else {\n this.buffer = new Float32Array(0);\n }\n return outputBuffer;\n };\n return WebsocketClient;\n}());\nvar ctx = self;\nvar websocketClient = new WebsocketClient(ctx);\nctx.onmessage = function (e) {\n switch (e.data.type) {\n case 'INIT':\n websocketClient.init(e.data.apiUrl, e.data.authToken, e.data.targetSampleRate, e.data.debug);\n break;\n case 'SET_SOURSE_SAMPLE_RATE':\n websocketClient.setSourceSampleRate(e.data.sourceSampleRate);\n break;\n case 'SET_SHARED_ARRAY_BUFFERS':\n websocketClient.setSharedArrayBuffers(e.data.controlSAB, e.data.dataSAB);\n break;\n case 'CLOSE':\n websocketClient.closeWebsocket();\n break;\n case 'START_CONTEXT':\n websocketClient.startContext(e.data.appId);\n break;\n case 'SWITCH_CONTEXT':\n websocketClient.switchContext(e.data.appId);\n break;\n case 'STOP_CONTEXT':\n websocketClient.stopContext();\n break;\n case 'AUDIO':\n websocketClient.sendAudio(e.data.payload);\n break;\n default:\n console.log('WORKER', e);\n }\n};\nfunction float32ToInt16(buffer) {\n var buf = new Int16Array(buffer.length);\n for (var l = 0; l < buffer.length; l++) {\n buf[l] = buffer[l] * (buffer[l] < 0 ? 0x8000 : 0x7fff);\n }\n return buf;\n}\nfunction generateFilter(sourceSampleRate, targetSampleRate, length) {\n if (length % 2 === 0) {\n throw Error('Filter length must be odd');\n }\n var cutoff = targetSampleRate / 2;\n var filter = new Float32Array(length);\n var sum = 0;\n for (var i = 0; i < length; i++) {\n var x = sinc(((2 * cutoff) / sourceSampleRate) * (i - (length - 1) / 2));\n sum += x;\n filter[i] = x;\n }\n for (var i = 0; i < length; i++) {\n filter[i] = filter[i] / sum;\n }\n return filter;\n}\nfunction sinc(x) {\n if (x === 0.0) {\n return 1.0;\n }\n var piX = Math.PI * x;\n return Math.sin(piX) / piX;\n}\n"; | ||
export default _default; |
@@ -91,3 +91,3 @@ "use strict"; | ||
if (isNaN(this.resampleRatio)) { | ||
throw Error('resampleRatio is NaN'); | ||
throw Error("resampleRatio is NaN source rate is " + this.sourceSampleRate + " and target rate is " + this.targetSampleRate); | ||
} | ||
@@ -94,0 +94,0 @@ }; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
186194
3284