UNPKG

@holzchopf/flp-file

Version:

Reads and writes FL Studio project and state files.

108 lines (107 loc) 3.28 kB
import { ArrayBufferStream, joinArrayBuffers } from "@holzchopf/array-buffer-stream"; import { FLPEvent } from "./flp-event"; import { FLPFileFormat } from "./flp-file-format"; /** * Class representing a chunk in an FLPFile. */ export class FLPChunk { constructor(type) { this.type = type; } } /** * Specific class for the header chunk. */ export class FLPHeaderChunk extends FLPChunk { /** * Name of file format. */ get formatName() { return FLPFileFormat.name(this.format); } getBinary() { const stream = new ArrayBufferStream(new ArrayBuffer(6)); stream.writeUint16(this.format, true); stream.writeUint16(this.channelCnt, true); stream.writeUint16(this.ppq, true); return stream.buffer; } setBinary(buffer) { const stream = new ArrayBufferStream(buffer); this.format = stream.readUint16(true); this.channelCnt = stream.readUint16(true); this.ppq = stream.readUint16(true); } constructor() { super('FLhd'); /** * Numeric file format identifier. */ this.format = -1; /** * Number of channels. */ this.channelCnt = 0; /** * Project PPQ. */ this.ppq = 96; } } /** * Specific class for the data chunk. */ export class FLPDataChunk extends FLPChunk { getBinary() { const buffers = []; this.events.forEach((event) => { const type = event.type; const bytes = event.getBinary(); // size is pre-defined for primitives let size = event.maxByteLength; if (size) { // total size is 1 (type) + event.size const stream = new ArrayBufferStream(new ArrayBuffer(1 + bytes.byteLength)); stream.writeUint8(type); stream.writeBytes(bytes); buffers.push(stream.buffer); } else { // total size is 1 (type) + max 16 (LEB128) + event.size const stream = new ArrayBufferStream(new ArrayBuffer(1 + 16 + bytes.byteLength)); stream.writeUint8(type); stream.writeUleb128(bytes.byteLength); stream.writeBytes(bytes); // only push used buffer buffers.push(stream.buffer.slice(0, stream.cursor)); } }); // concatenate all those ArrayBuffers return joinArrayBuffers(buffers); } setBinary(buffer) { const stream = new ArrayBufferStream(buffer); this.events = []; while (!stream.eof()) { const type = stream.readUint8(); const event = new FLPEvent(type); // size is pre-defined for primitives let size = event.maxByteLength; if (size) { event.setBinary(stream.readBytes(size)); } else { size = stream.readUleb128(); event.setBinary(stream.readBytes(size)); } this.events.push(event); } } constructor() { super('FLdt'); /** * FLPEvents in this chunk. */ this.events = []; } }