UNPKG

pw-client

Version:

Node.js wrapper for developing PipeWire clients

192 lines (191 loc) 8.62 kB
import { endianness } from "node:os"; function fpOutputBuffer(ctor) { class WrappedTypeArray { #buffer; constructor(buffer) { this.#buffer = buffer; } set(index, value) { this.#buffer[index] = value; } get buffer() { return this.#buffer.buffer; } subarray(offset, size) { return new WrappedTypeArray(this.#buffer.subarray(offset, size)); } } return (samples) => new WrappedTypeArray(new ctor(samples)); } function intOutputBuffer(ctor, encode) { class WrappedTypeArray { #buffer; constructor(buffer) { this.#buffer = buffer; } set(index, value) { const encoded = encode(value); this.#buffer[index] = encoded; } get buffer() { return this.#buffer.buffer; } subarray(offset, size) { return new WrappedTypeArray(this.#buffer.subarray(offset, size)); } } return (samples) => new WrappedTypeArray(new ctor(samples)); } function signedInt(bits) { const multiplier = 2 ** (bits - 1) - 0.5; return (n) => Math.floor(n * multiplier); } function unsignedInt(bits) { const multiplier = (2 ** bits - 1) / 2; return (n) => Math.floor((n + 1) * multiplier); } const Int8Buffer = intOutputBuffer(Int8Array, signedInt(8)); const Int16Buffer = intOutputBuffer(Int16Array, signedInt(16)); const Int32Buffer = intOutputBuffer(Int32Array, signedInt(32)); const Uint8Buffer = intOutputBuffer(Uint8Array, unsignedInt(8)); const Uint16Buffer = intOutputBuffer(Uint16Array, unsignedInt(16)); const Uint32Buffer = intOutputBuffer(Uint32Array, unsignedInt(32)); const Float32Buffer = fpOutputBuffer(Float32Array); const Float64Buffer = fpOutputBuffer(Float64Array); /** * Audio format class representing different sample formats supported by PipeWire. * Handles conversion between JavaScript Numbers and various binary audio formats. * * Users typically don't need to work with AudioFormat directly - it's handled * internally through quality presets and format negotiation. * * @class AudioFormat * * @example * ```typescript * // Access negotiated format info * console.log(`Stream format: ${stream.format.description}`); * console.log(`Sample rate: ${stream.rate}Hz`); * console.log(`Channels: ${stream.channels}`); * ``` */ export class AudioFormat { #enumValue; #byteSize; #bufferFactory; #description; constructor(value, byteSize, BufferClass, description) { this.#enumValue = value; this.#byteSize = byteSize; this.#bufferFactory = BufferClass; this.#description = description; AudioFormat.#enumMap.set(value, this); } get enumValue() { return this.#enumValue; } get byteSize() { return this.#byteSize; } get BufferClass() { return this.#bufferFactory; } get description() { return this.#description; } static #enumMap = new Map(); static fromEnum(format) { return AudioFormat.#enumMap.get(format); } static Int8 = new AudioFormat(0x101, 1, Int8Buffer, "8-bit signed integer (low quality)"); static Uint8 = new AudioFormat(0x102, 1, Uint8Buffer, "8-bit unsigned integer (basic quality)"); static get Int16() { return endianness() === "BE" ? AudioFormat.Int16BE : AudioFormat.Int16LE; } static get Uint16() { return endianness() === "BE" ? AudioFormat.Uint16BE : AudioFormat.Uint16LE; } static get Int24_32() { return endianness() === "BE" ? AudioFormat.Int24_32BE : AudioFormat.Int24_32LE; } static get Uint24_32() { return endianness() === "BE" ? AudioFormat.Uint24_32BE : AudioFormat.Uint24_32LE; } static get Int32() { return endianness() === "BE" ? AudioFormat.Int32BE : AudioFormat.Int32LE; } static get Uint32() { return endianness() === "BE" ? AudioFormat.Uint32BE : AudioFormat.Uint32LE; } // static get Int24() { // return endianness() === "BE" ? AudioFormat.Int24BE : AudioFormat.Int24LE; // } // static get Uint24() { // return endianness() === "BE" ? AudioFormat.Uint24BE : AudioFormat.Uint24LE; // } // static get Int20() { // return endianness() === "BE" ? AudioFormat.Int20BE : AudioFormat.Int20LE; // } // static get Uint20() { // return endianness() === "BE" ? AudioFormat.Uint20BE : AudioFormat.Uint20LE; // } // static get Int18() { // return endianness() === "BE" ? AudioFormat.Int18BE : AudioFormat.Int18LE; // } // static get Uint18() { // return endianness() === "BE" ? AudioFormat.Uint18BE : AudioFormat.Uint18LE; // } static get Float32() { return endianness() === "BE" ? AudioFormat.Float32BE : AudioFormat.Float32LE; } static get Float64() { return endianness() === "BE" ? AudioFormat.Float64BE : AudioFormat.Float64LE; } static ULaw = new AudioFormat(0x11f, 1, Int8Buffer, "μ-law compressed audio"); static ALaw = new AudioFormat(0x120, 1, Int8Buffer, "A-law compressed audio"); static Uint8Planar = new AudioFormat(0x201, 1, Uint8Buffer, "8-bit unsigned planar"); static Int16Planar = new AudioFormat(0x202, 2, Int16Buffer, "16-bit signed planar"); static Int24_32Planar = new AudioFormat(0x203, 4, Int32Buffer, "24-bit in 32-bit planar"); static Int32Planar = new AudioFormat(0x204, 4, Int32Buffer, "32-bit signed planar"); // static Int24Planar = new AudioFormat(0x205, 3); static Float32Planar = new AudioFormat(0x206, 4, Float32Buffer, "32-bit floating point planar"); static Float64Planar = new AudioFormat(0x207, 8, Float64Buffer, "64-bit floating point planar"); static Int8Planar = new AudioFormat(0x208, 1, Int8Buffer, "8-bit signed planar"); // Endian-specific static Int16LE = new AudioFormat(0x103, 2, Int16Buffer, "16-bit signed integer (standard quality)"); static Int16BE = new AudioFormat(0x104, 2, Int16Buffer, "16-bit signed integer (standard quality)"); static Uint16LE = new AudioFormat(0x105, 2, Uint16Buffer, "16-bit unsigned integer (standard quality)"); static Uint16BE = new AudioFormat(0x106, 2, Uint16Buffer, "16-bit unsigned integer (standard quality)"); static Int24_32LE = new AudioFormat(0x107, 4, Int32Buffer, "24-bit in 32-bit container (professional quality)"); static Int24_32BE = new AudioFormat(0x108, 4, Int32Buffer, "24-bit in 32-bit container (professional quality)"); static Uint24_32LE = new AudioFormat(0x109, 4, Uint32Buffer, "24-bit unsigned in 32-bit container (professional quality)"); static Uint24_32BE = new AudioFormat(0x10a, 4, Uint32Buffer, "24-bit unsigned in 32-bit container (professional quality)"); static Int32LE = new AudioFormat(0x10b, 4, Int32Buffer, "32-bit signed integer (high precision)"); static Int32BE = new AudioFormat(0x10c, 4, Int32Buffer, "32-bit signed integer (high precision)"); static Uint32LE = new AudioFormat(0x10d, 4, Uint32Buffer, "32-bit unsigned integer (high precision)"); static Uint32BE = new AudioFormat(0x10e, 4, Uint32Buffer, "32-bit unsigned integer (high precision)"); // private static Int24LE = new AudioFormat(0x10f, 3); // private static Int24BE = new AudioFormat(0x110, 3); // private static Uint24LE = new AudioFormat(0x111, 3); // private static Uint24BE = new AudioFormat(0x112, 3); // private static Int20LE = new AudioFormat(0x113, 4); // No idea how to encode... // private static Int20BE = new AudioFormat(0x114, 4); // No idea... // private static Uint20LE = new AudioFormat(0x115, 4); // No idea... // private static Uint20BE = new AudioFormat(0x116, 4); // No idea... // private static Int18LE = new AudioFormat(0x117, 3); // No idea... // private static Int18BE = new AudioFormat(0x118, 3); // No idea... // private static Uint18LE = new AudioFormat(0x119, 3); // No idea... // private static Uint18BE = new AudioFormat(0x11a, 3); // No idea... static Float32LE = new AudioFormat(0x11b, 4, Float32Buffer, "32-bit floating point (excellent quality)"); static Float32BE = new AudioFormat(0x11c, 4, Float32Buffer, "32-bit floating point (excellent quality)"); static Float64LE = new AudioFormat(0x11d, 8, Float64Buffer, "64-bit floating point (highest precision)"); static Float64BE = new AudioFormat(0x11e, 8, Float64Buffer, "64-bit floating point (highest precision)"); }