| ; | |
| /*! | |
| * Copyright (c) 2026-present, Vanilagy and contributors | |
| * | |
| * This Source Code Form is subject to the terms of the Mozilla Public | |
| * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| * file, You can obtain one at https://mozilla.org/MPL/2.0/. | |
| */ | |
| var __importDefault = (this && this.__importDefault) || function (mod) { | |
| return (mod && mod.__esModule) ? mod : { "default": mod }; | |
| }; | |
| Object.defineProperty(exports, "__esModule", { value: true }); | |
| const flac_1 = __importDefault(require("../build/flac")); | |
| let module; | |
| let modulePromise = null; | |
| let initEncoderFn; | |
| let getEncodeInputPtr; | |
| let sendSamplesFn; | |
| let getOutputData; | |
| let getFrameCount; | |
| let getFrameSize; | |
| let getFrameSamples; | |
| let getHeaderData; | |
| let getHeaderSize; | |
| let finishEncoderFn; | |
| const ensureModule = async () => { | |
| if (!module) { | |
| if (modulePromise) { | |
| return modulePromise; | |
| } | |
| modulePromise = (0, flac_1.default)(); | |
| module = await modulePromise; | |
| modulePromise = null; | |
| initEncoderFn = module.cwrap('init_encoder', 'number', ['number', 'number', 'number']); | |
| getEncodeInputPtr = module.cwrap('get_encode_input_ptr', 'number', ['number', 'number']); | |
| sendSamplesFn = module.cwrap('send_samples', 'number', ['number', 'number']); | |
| getOutputData = module.cwrap('get_output_data', 'number', ['number']); | |
| getFrameCount = module.cwrap('get_frame_count', 'number', ['number']); | |
| getFrameSize = module.cwrap('get_frame_size', 'number', ['number', 'number']); | |
| getFrameSamples = module.cwrap('get_frame_samples', 'number', ['number', 'number']); | |
| getHeaderData = module.cwrap('get_header_data', 'number', ['number']); | |
| getHeaderSize = module.cwrap('get_header_size', 'number', ['number']); | |
| finishEncoderFn = module.cwrap('finish_encoder', 'number', ['number']); | |
| } | |
| }; | |
| const initEncoder = async (numberOfChannels, sampleRate, bitsPerSample) => { | |
| await ensureModule(); | |
| const ctx = initEncoderFn(numberOfChannels, sampleRate, bitsPerSample); | |
| if (ctx === 0) { | |
| throw new Error('Failed to initialize FLAC encoder.'); | |
| } | |
| const headerPtr = getHeaderData(ctx); | |
| const headerSize = getHeaderSize(ctx); | |
| const header = module.HEAPU8.slice(headerPtr, headerPtr + headerSize).buffer; | |
| return { ctx, header }; | |
| }; | |
| const readPackets = (ctx) => { | |
| const packets = []; | |
| const frameCount = getFrameCount(ctx); | |
| const outputPtr = getOutputData(ctx); | |
| let offset = 0; | |
| for (let i = 0; i < frameCount; i++) { | |
| const size = getFrameSize(ctx, i); | |
| const samples = getFrameSamples(ctx, i); | |
| const encodedData = module.HEAPU8.slice(outputPtr + offset, outputPtr + offset + size).buffer; | |
| packets.push({ encodedData, samples }); | |
| offset += size; | |
| } | |
| return packets; | |
| }; | |
| const encode = (ctx, audioData, numSamples) => { | |
| const audioBytes = new Uint8Array(audioData); | |
| const inputPtr = getEncodeInputPtr(ctx, audioBytes.length); | |
| if (inputPtr === 0) { | |
| throw new Error('Failed to allocate encoder input buffer.'); | |
| } | |
| module.HEAPU8.set(audioBytes, inputPtr); | |
| const ret = sendSamplesFn(ctx, numSamples); | |
| if (ret < 0) { | |
| throw new Error(`Encode failed with error code ${ret}.`); | |
| } | |
| return readPackets(ctx); | |
| }; | |
| const flush = (ctx) => { | |
| const ret = finishEncoderFn(ctx); | |
| if (ret < 0) { | |
| throw new Error('Flush failed.'); | |
| } | |
| return readPackets(ctx); | |
| }; | |
| const onMessage = (data) => { | |
| const { id, command } = data; | |
| const handleCommand = async () => { | |
| try { | |
| let result; | |
| const transferables = []; | |
| switch (command.type) { | |
| case 'init': | |
| { | |
| const { ctx, header } = await initEncoder(command.data.numberOfChannels, command.data.sampleRate, command.data.bitsPerSample); | |
| result = { type: command.type, ctx, header }; | |
| transferables.push(header); | |
| } | |
| ; | |
| break; | |
| case 'encode': | |
| { | |
| const packets = encode(command.data.ctx, command.data.audioData, command.data.numSamples); | |
| for (const p of packets) { | |
| transferables.push(p.encodedData); | |
| } | |
| result = { type: command.type, packets }; | |
| } | |
| ; | |
| break; | |
| case 'flush': | |
| { | |
| const packets = flush(command.data.ctx); | |
| for (const p of packets) { | |
| transferables.push(p.encodedData); | |
| } | |
| result = { type: command.type, packets }; | |
| } | |
| ; | |
| break; | |
| } | |
| const response = { | |
| id, | |
| success: true, | |
| data: result, | |
| }; | |
| sendMessage(response, transferables); | |
| } | |
| catch (error) { | |
| const response = { | |
| id, | |
| success: false, | |
| error, | |
| }; | |
| sendMessage(response); | |
| } | |
| }; | |
| void handleCommand(); | |
| }; | |
| const sendMessage = (data, transferables) => { | |
| if (parentPort) { | |
| parentPort.postMessage(data, transferables ?? []); | |
| } | |
| else { | |
| self.postMessage(data, { transfer: transferables ?? [] }); | |
| } | |
| }; | |
| let parentPort = null; | |
| try { | |
| // We're in Node.js (or a runtime that mimics it) | |
| const workerModule = 'worker_threads'; | |
| // eslint-disable-next-line @stylistic/max-len | |
| // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-require-imports, @typescript-eslint/no-unsafe-member-access | |
| parentPort = require(workerModule).parentPort; | |
| } | |
| catch { | |
| // Web worker (browser, Deno), no require available | |
| } | |
| if (parentPort) { | |
| parentPort.on('message', onMessage); | |
| } | |
| else { | |
| self.addEventListener('message', event => onMessage(event.data)); | |
| } | |
| // Prevents the worker for being randomly closed by Firefox | |
| // https://github.com/Vanilagy/mediabunny/issues/435 | |
| setInterval(() => { }, 1000); | |
Xet Storage Details
- Size:
- 6.33 kB
- Xet hash:
- 47ea8bdf669c95344d975dbaa54365d7db54da9626b0799cdf705acc09f48c51
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.