UNPKG

whisper.rn

Version:

React Native binding of whisper.cpp

143 lines (132 loc) 4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RingBuffer = void 0; /** * RingBuffer - A fixed-size circular buffer for audio data * * This class implements a ring buffer (circular buffer) that maintains * a fixed memory footprint regardless of how much data is written. * It's designed for pre-recording audio where we only need to keep * the last N seconds of audio before speech is detected. * * Key features: * - Fixed memory allocation (no unbounded growth) * - O(1) write operations * - Preserves most recent data when buffer is full */ class RingBuffer { writeIndex = 0; dataLength = 0; /** * Create a new RingBuffer * @param maxBytes Maximum buffer size in bytes */ constructor(maxBytes) { this.maxBytes = maxBytes; this.buffer = new Uint8Array(maxBytes); } /** * Write audio data to the buffer * If data exceeds buffer capacity, oldest data is overwritten * @param data Audio data to write */ write(data) { if (data.length === 0) return; if (data.length >= this.maxBytes) { // Data is larger than buffer, only keep the last maxBytes const startOffset = data.length - this.maxBytes; this.buffer.set(data.subarray(startOffset)); this.writeIndex = 0; this.dataLength = this.maxBytes; return; } const spaceToEnd = this.maxBytes - this.writeIndex; if (data.length <= spaceToEnd) { // Data fits without wrapping this.buffer.set(data, this.writeIndex); this.writeIndex += data.length; if (this.writeIndex >= this.maxBytes) { this.writeIndex = 0; } } else { // Data needs to wrap around this.buffer.set(data.subarray(0, spaceToEnd), this.writeIndex); const remaining = data.length - spaceToEnd; this.buffer.set(data.subarray(spaceToEnd), 0); this.writeIndex = remaining; } // Update data length (capped at maxBytes) this.dataLength = Math.min(this.dataLength + data.length, this.maxBytes); } /** * Read all available data from the buffer in correct order * Does NOT clear the buffer (use clear() for that) * @returns Uint8Array containing the buffered data in order */ read() { if (this.dataLength === 0) { return new Uint8Array(0); } const result = new Uint8Array(this.dataLength); if (this.dataLength < this.maxBytes) { // Buffer hasn't wrapped yet, data starts at 0 result.set(this.buffer.subarray(0, this.dataLength)); } else { // Buffer has wrapped, need to reconstruct order const readStart = this.writeIndex; const firstPartLength = this.maxBytes - readStart; // Copy from readStart to end result.set(this.buffer.subarray(readStart, this.maxBytes), 0); // Copy from start to writeIndex result.set(this.buffer.subarray(0, this.writeIndex), firstPartLength); } return result; } /** * Clear the buffer and reset indices */ clear() { this.writeIndex = 0; this.dataLength = 0; // Note: We don't need to zero the buffer, just reset indices } /** * Get the current amount of data in the buffer * @returns Number of bytes currently in the buffer */ getLength() { return this.dataLength; } /** * Get the maximum capacity of the buffer * @returns Maximum buffer size in bytes */ getCapacity() { return this.maxBytes; } /** * Check if the buffer is empty * @returns true if buffer contains no data */ isEmpty() { return this.dataLength === 0; } /** * Check if the buffer is full * @returns true if buffer has reached capacity */ isFull() { return this.dataLength >= this.maxBytes; } /** * Get the fill percentage of the buffer * @returns Number between 0 and 1 representing how full the buffer is */ getFillRatio() { return this.dataLength / this.maxBytes; } } exports.RingBuffer = RingBuffer; //# sourceMappingURL=RingBuffer.js.map