@euirim/microsoft-cognitiveservices-speech-sdk
Version:
Microsoft Cognitive Services Speech SDK for JavaScript
123 lines (121 loc) • 5.64 kB
JavaScript
"use strict";
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
Object.defineProperty(exports, "__esModule", { value: true });
var Exports_1 = require("../common/Exports");
var ReplayableAudioNode = /** @class */ (function () {
function ReplayableAudioNode(audioSource, format) {
var _this = this;
this.privBuffers = [];
this.privReplayOffset = 0;
this.privLastShrinkOffset = 0;
this.privBufferStartOffset = 0;
this.privBufferSerial = 0;
this.privBufferedBytes = 0;
this.privReplay = false;
this.privLastChunkAcquiredTime = 0;
this.id = function () {
return _this.privAudioNode.id();
};
this.privAudioNode = audioSource;
this.privFormat = format;
}
// Reads and returns the next chunk of audio buffer.
// If replay of existing buffers are needed, read() will first seek and replay
// existing content, and upoin completion it will read new content from the underlying
// audio node, saving that content into the replayable buffers.
ReplayableAudioNode.prototype.read = function () {
var _this = this;
// if there is a replay request to honor.
if (!!this.privReplay && this.privBuffers.length !== 0) {
// Find the start point in the buffers.
// Offsets are in 100ns increments.
// So how many bytes do we need to seek to get the right offset?
var offsetToSeek = this.privReplayOffset - this.privBufferStartOffset;
var bytesToSeek = Math.round(offsetToSeek * this.privFormat.avgBytesPerSec * 1e-7);
if (0 !== (bytesToSeek % 2)) {
bytesToSeek++;
}
var i = 0;
while (i < this.privBuffers.length && bytesToSeek >= this.privBuffers[i].chunk.buffer.byteLength) {
bytesToSeek -= this.privBuffers[i++].chunk.buffer.byteLength;
}
var retVal = this.privBuffers[i].chunk.buffer.slice(bytesToSeek);
this.privReplayOffset += (retVal.byteLength / this.privFormat.avgBytesPerSec) * 1e+7;
// If we've reached the end of the buffers, stop replaying.
if (i === this.privBuffers.length - 1) {
this.privReplay = false;
}
return Exports_1.PromiseHelper.fromResult({
buffer: retVal,
isEnd: false,
timeReceived: this.privBuffers[i].chunk.timeReceived,
});
}
return this.privAudioNode.read()
.onSuccessContinueWith(function (result) {
if (result.buffer) {
_this.privBuffers.push(new BufferEntry(result, _this.privBufferSerial++, _this.privBufferedBytes));
_this.privBufferedBytes += result.buffer.byteLength;
}
return result;
});
};
ReplayableAudioNode.prototype.detach = function () {
this.privAudioNode.detach();
this.privBuffers = undefined;
};
ReplayableAudioNode.prototype.replay = function () {
if (this.privBuffers && 0 !== this.privBuffers.length) {
this.privReplay = true;
this.privReplayOffset = this.privLastShrinkOffset;
}
};
// Shrinks the existing audio buffers to start at the new offset, or at the
// beginning of the buffer closest to the requested offset.
// A replay request will start from the last shrink point.
ReplayableAudioNode.prototype.shrinkBuffers = function (offset) {
this.privLastShrinkOffset = offset;
// Find the start point in the buffers.
// Offsets are in 100ns increments.
// So how many bytes do we need to seek to get the right offset?
var offsetToSeek = offset - this.privBufferStartOffset;
var bytesToSeek = Math.round(offsetToSeek * this.privFormat.avgBytesPerSec * 1e-7);
var i = 0;
while (i < this.privBuffers.length && bytesToSeek >= this.privBuffers[i].chunk.buffer.byteLength) {
bytesToSeek -= this.privBuffers[i++].chunk.buffer.byteLength;
}
this.privBufferStartOffset = Math.round(offset - ((bytesToSeek / this.privFormat.avgBytesPerSec) * 1e+7));
this.privBuffers = this.privBuffers.slice(i);
};
// Finds the time a buffer of audio was first seen by offset.
ReplayableAudioNode.prototype.findTimeAtOffset = function (offset) {
if (offset < this.privBufferStartOffset) {
return 0;
}
for (var _i = 0, _a = this.privBuffers; _i < _a.length; _i++) {
var value = _a[_i];
var startOffset = (value.byteOffset / this.privFormat.avgBytesPerSec) * 1e7;
var endOffset = startOffset + ((value.chunk.buffer.byteLength / this.privFormat.avgBytesPerSec) * 1e7);
if (offset >= startOffset && offset <= endOffset) {
return value.chunk.timeReceived;
}
}
return 0;
};
return ReplayableAudioNode;
}());
exports.ReplayableAudioNode = ReplayableAudioNode;
// Primary use of this class is to help debugging problems with the replay
// code. If the memory cost of alloc / dealloc gets too much, drop it and just use
// the ArrayBuffer directly.
// tslint:disable-next-line:max-classes-per-file
var BufferEntry = /** @class */ (function () {
function BufferEntry(chunk, serial, byteOffset) {
this.chunk = chunk;
this.serial = serial;
this.byteOffset = byteOffset;
}
return BufferEntry;
}());
//# sourceMappingURL=ReplayableAudioNode.js.map