UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

167 lines (166 loc) 6.26 kB
import { o as __toESM } from "./chunk-CNf5ZN-e.js"; import { t as require_src } from "./src-6PhJB9jV.js"; import { E as Uint8ArrayType, S as UINT32_LE, T as UINT8, b as UINT24_LE, o as makeUnexpectedFileContentError, t as BasicParser, v as UINT16_LE } from "./BasicParser-CSYy5xVJ.js"; import { d as uint8ArrayToHex } from "./Util--vOO_7DL.js"; import { i as FourCcToken, r as tryParseApeHeader } from "./APEv2Parser-Drjv2OIw.js"; //#region node_modules/music-metadata/lib/wavpack/WavPackToken.js const SampleRates = [ 6e3, 8e3, 9600, 11025, 12e3, 16e3, 22050, 24e3, 32e3, 44100, 48e3, 64e3, 88200, 96e3, 192e3, -1 ]; /** * WavPack Block Header * * 32-byte little-endian header at the front of every WavPack block * * Ref: http://www.wavpack.com/WavPack5FileFormat.pdf (page 2/6: 2.0 "Block Header") */ const BlockHeaderToken = { len: 32, get: (buf, off) => { const flags = UINT32_LE.get(buf, off + 24); const res = { BlockID: FourCcToken.get(buf, off), blockSize: UINT32_LE.get(buf, off + 4), version: UINT16_LE.get(buf, off + 8), totalSamples: UINT32_LE.get(buf, off + 12), blockIndex: UINT32_LE.get(buf, off + 16), blockSamples: UINT32_LE.get(buf, off + 20), flags: { bitsPerSample: (1 + getBitAllignedNumber(flags, 0, 2)) * 8, isMono: isBitSet(flags, 2), isHybrid: isBitSet(flags, 3), isJointStereo: isBitSet(flags, 4), crossChannel: isBitSet(flags, 5), hybridNoiseShaping: isBitSet(flags, 6), floatingPoint: isBitSet(flags, 7), samplingRate: SampleRates[getBitAllignedNumber(flags, 23, 4)], isDSD: isBitSet(flags, 31) }, crc: new Uint8ArrayType(4).get(buf, off + 28) }; if (res.flags.isDSD) res.totalSamples *= 8; return res; } }; /** * 3.0 Metadata Sub-Blocks * Ref: http://www.wavpack.com/WavPack5FileFormat.pdf (page 4/6: 3.0 "Metadata Sub-Block") */ const MetadataIdToken = { len: 1, get: (buf, off) => { return { functionId: getBitAllignedNumber(buf[off], 0, 6), isOptional: isBitSet(buf[off], 5), isOddSize: isBitSet(buf[off], 6), largeBlock: isBitSet(buf[off], 7) }; } }; function isBitSet(flags, bitOffset) { return getBitAllignedNumber(flags, bitOffset, 1) === 1; } function getBitAllignedNumber(flags, bitOffset, len) { return flags >>> bitOffset & 4294967295 >>> 32 - len; } const debug = (0, (/* @__PURE__ */ __toESM(require_src(), 1)).default)("music-metadata:parser:WavPack"); var WavPackContentError = class extends makeUnexpectedFileContentError("WavPack") {}; /** * WavPack Parser */ var WavPackParser = class extends BasicParser { constructor() { super(...arguments); this.audioDataSize = 0; } async parse() { this.metadata.setAudioOnly(); this.audioDataSize = 0; await this.parseWavPackBlocks(); return tryParseApeHeader(this.metadata, this.tokenizer, this.options); } async parseWavPackBlocks() { do { if (await this.tokenizer.peekToken(FourCcToken) !== "wvpk") break; const header = await this.tokenizer.readToken(BlockHeaderToken); if (header.BlockID !== "wvpk") throw new WavPackContentError("Invalid WavPack Block-ID"); debug(`WavPack header blockIndex=${header.blockIndex}, len=${BlockHeaderToken.len}`); if (header.blockIndex === 0 && !this.metadata.format.container) { this.metadata.setFormat("container", "WavPack"); this.metadata.setFormat("lossless", !header.flags.isHybrid); this.metadata.setFormat("bitsPerSample", header.flags.bitsPerSample); if (!header.flags.isDSD) { this.metadata.setFormat("sampleRate", header.flags.samplingRate); this.metadata.setFormat("duration", header.totalSamples / header.flags.samplingRate); } this.metadata.setFormat("numberOfChannels", header.flags.isMono ? 1 : 2); this.metadata.setFormat("numberOfSamples", header.totalSamples); this.metadata.setFormat("codec", header.flags.isDSD ? "DSD" : "PCM"); } const ignoreBytes = header.blockSize - (BlockHeaderToken.len - 8); await (header.blockIndex === 0 ? this.parseMetadataSubBlock(header, ignoreBytes) : this.tokenizer.ignore(ignoreBytes)); if (header.blockSamples > 0) this.audioDataSize += header.blockSize; } while (!this.tokenizer.fileInfo.size || this.tokenizer.fileInfo.size - this.tokenizer.position >= BlockHeaderToken.len); if (this.metadata.format.duration) this.metadata.setFormat("bitrate", this.audioDataSize * 8 / this.metadata.format.duration); } /** * Ref: http://www.wavpack.com/WavPack5FileFormat.pdf, 3.0 Metadata Sub-blocks * @param header Header * @param remainingLength Remaining length */ async parseMetadataSubBlock(header, remainingLength) { let remaining = remainingLength; while (remaining > MetadataIdToken.len) { const id = await this.tokenizer.readToken(MetadataIdToken); const dataSizeInWords = await this.tokenizer.readNumber(id.largeBlock ? UINT24_LE : UINT8); const data = new Uint8Array(dataSizeInWords * 2 - (id.isOddSize ? 1 : 0)); await this.tokenizer.readBuffer(data); debug(`Metadata Sub-Blocks functionId=0x${id.functionId.toString(16)}, id.largeBlock=${id.largeBlock},data-size=${data.length}`); switch (id.functionId) { case 0: break; case 14: { debug("ID_DSD_BLOCK"); const mp = 1 << UINT8.get(data, 0); const samplingRate = header.flags.samplingRate * mp * 8; if (!header.flags.isDSD) throw new WavPackContentError("Only expect DSD block if DSD-flag is set"); this.metadata.setFormat("sampleRate", samplingRate); this.metadata.setFormat("duration", header.totalSamples / samplingRate); break; } case 36: debug("ID_ALT_TRAILER: trailer for non-wav files"); break; case 38: this.metadata.setFormat("audioMD5", data); break; case 47: debug(`ID_BLOCK_CHECKSUM: checksum=${uint8ArrayToHex(data)}`); break; default: debug(`Ignore unsupported meta-sub-block-id functionId=0x${id.functionId.toString(16)}`); break; } remaining -= MetadataIdToken.len + (id.largeBlock ? UINT24_LE.len : UINT8.len) + dataSizeInWords * 2; debug(`remainingLength=${remaining}`); if (id.isOddSize) this.tokenizer.ignore(1); } if (remaining !== 0) throw new WavPackContentError("metadata-sub-block should fit it remaining length"); } }; //#endregion export { WavPackParser };