UNPKG

echogarden

Version:

An easy-to-use speech toolset. Includes tools for synthesis, recognition, alignment, speech translation, language detection, source separation and more.

440 lines 13 kB
import { decodeUtf8, encodeUtf8 } from "../encodings/Utf8.js"; import { concatUint8Arrays } from "./Utilities.js"; export class WasmMemoryManager { wasmModule; wasmAlloc; wasmFree; allocatedReferences = new Set(); constructor(wasmModule, options) { options = options ?? {}; this.wasmModule = wasmModule; if (options.wasmAlloc) { this.wasmAlloc = options.wasmAlloc; } else { if (!wasmModule._malloc) { throw new Error(`Couldn't find a '_malloc' function in the module and no custom 'wasmAlloc' was provided in the options`); } this.wasmAlloc = wasmModule._malloc; } if (options.wasmFree) { this.wasmFree = options.wasmFree; } else { if (!wasmModule._free) { throw new Error(`Couldn't find a '_malloc' function in the module and no custom 'wasmFree' was provided in the options`); } this.wasmFree = wasmModule._free; } } allocInt8() { const address = this.alloc(1); return this.wrapInt8(address).clear(); } wrapInt8(address) { const ref = new Int8Ref(address, this); this.allocatedReferences.add(ref); return ref; } allocUint8() { const address = this.alloc(1); return this.wrapUint8(address).clear(); } wrapUint8(address) { const ref = new Uint8Ref(address, this); this.allocatedReferences.add(ref); return ref; } allocInt16() { const address = this.alloc(2); return this.wrapInt16(address).clear(); } wrapInt16(address) { const ref = new Int16Ref(address, this); this.allocatedReferences.add(ref); return ref; } allocUint16() { const address = this.alloc(2); return this.wrapUint16(address).clear(); } wrapUint16(address) { const ref = new Uint16Ref(address, this); this.allocatedReferences.add(ref); return ref; } allocInt32() { const address = this.alloc(4); return this.wrapInt32(address).clear(); } wrapInt32(address) { const ref = new Int32Ref(address, this); this.allocatedReferences.add(ref); return ref; } allocUint32() { const address = this.alloc(4); return this.wrapUint32(address).clear(); } wrapUint32(address) { const ref = new Uint32Ref(address, this); this.allocatedReferences.add(ref); return ref; } allocPointer() { const address = this.alloc(4); return this.wrapPointer(address).clear(); } wrapPointer(address) { const ref = new PointerRef(address, this); this.allocatedReferences.add(ref); return ref; } allocFloat32() { const address = this.alloc(4); return this.wrapFloat64(address).clear(); } wrapFloat32(address) { const ref = new Float32Ref(address, this); this.allocatedReferences.add(ref); return ref; } allocFloat64() { const address = this.alloc(8); return this.wrapFloat64(address).clear(); } wrapFloat64(address) { const ref = new Float64Ref(address, this); this.allocatedReferences.add(ref); return ref; } // Allocate or wrap arrays allocInt8Array(length) { const address = this.alloc(length << 0); return this.wrapInt8Array(address, length).clear(); } wrapInt8Array(address, length) { const ref = new Int8ArrayRef(address, length, this); this.allocatedReferences.add(ref); return ref; } allocUint8Array(length) { const address = this.alloc(length << 0); return this.wrapUint8Array(address, length).clear(); } wrapUint8Array(address, length) { const ref = new Uint8ArrayRef(address, length, this); this.allocatedReferences.add(ref); return ref; } allocInt16Array(length) { const address = this.alloc(length << 1); return this.wrapInt16Array(address, length).clear(); } wrapInt16Array(address, length) { const ref = new Int16ArrayRef(address, length, this); this.allocatedReferences.add(ref); return ref; } allocUint16Array(length) { const address = this.alloc(length << 1); return this.wrapUint16Array(address, length).clear(); } wrapUint16Array(address, length) { const ref = new Uint16ArrayRef(address, length, this); this.allocatedReferences.add(ref); return ref; } allocInt32Array(length) { const address = this.alloc(length << 2); return this.wrapInt32Array(address, length).clear(); } wrapInt32Array(address, length) { const ref = new Int32ArrayRef(address, length, this); this.allocatedReferences.add(ref); return ref; } allocUint32Array(length) { const address = this.alloc(length << 2); return this.wrapUint32Array(address, length).clear(); } wrapUint32Array(address, length) { const ref = new Uint32ArrayRef(address, length, this); this.allocatedReferences.add(ref); return ref; } allocFloat32Array(length) { const address = this.alloc(length << 2); return this.wrapFloat32Array(address, length).clear(); } wrapFloat32Array(address, length) { const ref = new Float32ArrayRef(address, length, this); this.allocatedReferences.add(ref); return ref; } allocFloat64Array(length) { const address = this.alloc(length << 3); return this.wrapFloat64Array(address, length).clear(); } wrapFloat64Array(address, length) { const ref = new Float64ArrayRef(address, length, this); this.allocatedReferences.add(ref); return ref; } allocNullTerminatedUtf8String(str) { const strBuffer = concatUint8Arrays([encodeUtf8(str), new Uint8Array(1)]); const ref = this.allocUint8Array(strBuffer.length); ref.view.set(strBuffer); return ref; } wrapNullTerminatedUtf8String(address) { const ref = new NullTerminatedUtf8StringRef(address, this); this.allocatedReferences.add(ref); return ref; } alloc(size) { const ptr = this.wasmAlloc(size); return ptr; } free(wasmReference) { if (wasmReference.isFreed) { return; } this.wasmFree(wasmReference.address); this.allocatedReferences.delete(wasmReference); wasmReference.clearAddress(); } freeAll() { for (const wasmReference of this.allocatedReferences) { this.free(wasmReference); } } detach(wasmReference) { this.allocatedReferences.delete(wasmReference); return wasmReference; } } class ValueRef { ptr; manager; get module() { return this.manager.wasmModule; } constructor(ptr, manager) { this.ptr = ptr; this.manager = manager; } get value() { this.assertNotFreed(); return this.getValue(); } set value(newValue) { this.assertNotFreed(); this.setValue(newValue); } get address() { this.assertNotFreed(); return this.ptr; } clear() { this.assertNotFreed(); if (typeof this.value == 'number') { this.value = 0; } else if (typeof this.value == 'string') { throw new Error('Unimplemented'); } return this; } free() { this.manager.free(this); } detach() { return this.manager.detach(this); } clearAddress() { this.ptr = 0; } get isFreed() { return this.ptr == 0; } assertNotFreed() { if (this.isFreed) { throw new Error('Attempt to read a freed WASM value reference.'); } } } export class Int8Ref extends ValueRef { getValue() { return this.module.HEAP8[this.ptr >>> 0]; } setValue(newValue) { this.module.HEAP8[this.ptr >>> 0] = newValue; } } export class Uint8Ref extends ValueRef { getValue() { return this.module.HEAPU8[this.ptr >>> 0]; } setValue(newValue) { this.module.HEAPU8[this.ptr >>> 0] = newValue; } } export class Int16Ref extends ValueRef { getValue() { return this.module.HEAP16[this.ptr >>> 1]; } setValue(newValue) { this.module.HEAP16[this.ptr >>> 1] = newValue; } } export class Uint16Ref extends ValueRef { getValue() { return this.module.HEAPU16[this.ptr >>> 1]; } setValue(newValue) { this.module.HEAPU16[this.ptr >>> 1] = newValue; } } export class Int32Ref extends ValueRef { getValue() { return this.module.HEAP32[this.ptr >>> 2]; } setValue(newValue) { this.module.HEAP32[this.ptr >>> 2] = newValue; } } export class Uint32Ref extends ValueRef { getValue() { return this.module.HEAPU32[this.ptr >>> 2]; } setValue(newValue) { this.module.HEAPU32[this.ptr >>> 2] = newValue; } } export class PointerRef extends Uint32Ref { } export class Float32Ref extends ValueRef { getValue() { return this.module.HEAPF32[this.ptr >>> 2]; } setValue(newValue) { this.module.HEAPF32[this.ptr >>> 2] = newValue; } } export class Float64Ref extends ValueRef { getValue() { return this.module.HEAPF64[this.ptr >>> 3]; } setValue(newValue) { this.module.HEAPF64[this.ptr >>> 3] = newValue; } } export class NullTerminatedUtf8StringRef extends ValueRef { getValue() { const ptr = this.ptr >>> 0; const heapU8 = this.module.HEAPU8; const endByteOffset = heapU8.subarray(ptr).indexOf(0); const strBytes = heapU8.subarray(ptr, ptr + endByteOffset); const str = decodeUtf8(strBytes); return str; } setValue(newValue) { throw new Error('Unimplemented'); } } class TypedArrayRef { ptr; length; manager; get module() { return this.manager.wasmModule; } constructor(ptr, length, manager) { this.ptr = ptr; this.length = length; this.manager = manager; } get view() { this.assertNotFreed(); return this.getView(); } slice(start, end) { return this.view.slice(start, end); } get address() { this.assertNotFreed(); return this.ptr; } clear() { this.view.fill(0); return this; } free() { this.manager.free(this); } clearAddress() { this.ptr = 0; } detach() { return this.manager.detach(this); } get isFreed() { return this.ptr == 0; } assertNotFreed() { if (this.isFreed) { throw new Error('Attempt to read a freed WASM typed array reference.'); } } } export class Int8ArrayRef extends TypedArrayRef { getView() { const startIndex = this.ptr >>> 0; return this.module.HEAP8.subarray(startIndex, startIndex + this.length); } } export class Uint8ArrayRef extends TypedArrayRef { getView() { const startIndex = this.ptr >>> 0; return this.module.HEAPU8.subarray(startIndex, startIndex + this.length); } readAsNullTerminatedUtf8String() { let strBytes = this.view; const indexOfFirstZero = strBytes.indexOf(0); if (indexOfFirstZero >= 0) { strBytes = strBytes.subarray(0, indexOfFirstZero); } const str = decodeUtf8(strBytes); return str; } } export class Int16ArrayRef extends TypedArrayRef { getView() { const startIndex = this.ptr >>> 1; return this.module.HEAP16.subarray(startIndex, startIndex + this.length); } } export class Uint16ArrayRef extends TypedArrayRef { getView() { const startIndex = this.ptr >>> 1; return this.module.HEAPU16.subarray(startIndex, startIndex + this.length); } } export class Int32ArrayRef extends TypedArrayRef { getView() { const startIndex = this.ptr >>> 2; return this.module.HEAP32.subarray(startIndex, startIndex + this.length); } } export class Uint32ArrayRef extends TypedArrayRef { getView() { const startIndex = this.ptr >>> 2; return this.module.HEAPU32.subarray(startIndex, startIndex + this.length); } } export class Float32ArrayRef extends TypedArrayRef { getView() { const startIndex = this.ptr >>> 2; return this.module.HEAPF32.subarray(startIndex, startIndex + this.length); } } export class Float64ArrayRef extends TypedArrayRef { getView() { const startIndex = this.ptr >>> 3; return this.module.HEAPF64.subarray(startIndex, startIndex + this.length); } } //# sourceMappingURL=WasmMemoryManager.js.map