furnace-module-interface
Version:
An interface for loading, processing and saving furnace modules in an object-oriented manner. Fully typed via TypeScript.
199 lines (198 loc) • 7.76 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Furnace16bitSample = exports.Furnace8bitSample = exports.FurnaceSample = void 0;
const defaults_1 = require("./defaults");
class FurnaceSample {
constructor() {
this.name = defaults_1.defaults.sampleName;
this.compatRate = defaults_1.defaults.sampleRate;
this.c4Rate = defaults_1.defaults.sampleRate;
this.loopStart = null;
this.loopEnd = null;
this.volume = null;
this.pitch = null;
this.data = Furnace8bitSample.create();
this.precense = [0, 0, 0, 0,];
}
static create() {
return new FurnaceSample();
}
static fromHelper(helper, version) {
const sample = FurnaceSample.create();
const _magic = helper.getASCII(4);
const old = FurnaceSample.magic === _magic;
if (!old && FurnaceSample.magic2 !== _magic) {
throw new Error("Expected format magic string \"" + FurnaceSample.magic + "\" or \"" + FurnaceSample.magic2 + "\" when loading a sample block.");
}
helper.skipBytes(4);
sample.name = helper.readString("utf-8");
const length = helper.readUInt32LE();
sample.compatRate = helper.readUInt32LE();
if (old) {
sample.volume = helper.readInt16LE();
sample.pitch = helper.readInt16LE();
if (version >= 58) {
sample.volume = null;
sample.pitch = null;
}
}
else {
sample.volume = null;
sample.pitch = null;
sample.c4Rate = helper.readUInt32LE();
}
const format = helper.readUInt8();
const loadFormat = FurnaceSample.getFormatFunctionFromId(format);
if (old) {
helper.skipBytes(1);
sample.c4Rate = helper.readUInt16LE();
sample.loopStart = helper.readUInt32LE();
sample.loopEnd = length;
sample.precense = [0, 0, 0, 0,];
}
else {
helper.skipBytes(3);
sample.loopStart = helper.readUInt32LE();
sample.loopEnd = helper.readUInt32LE();
sample.precense = [helper.readUInt32LE(), helper.readUInt32LE(), helper.readUInt32LE(), helper.readUInt32LE(),];
}
if (sample.loopStart === 0xFFFFFFFF) {
sample.loopStart = null;
}
if (sample.loopEnd === 0xFFFFFFFF) {
sample.loopEnd = null;
}
const pos = helper.getPosition(0);
const buf = helper.buffer.subarray(pos, pos + (length * (version < 58 ? 2 : FurnaceSample.getFormatMultiply(format))));
sample.data = loadFormat(buf, length);
return sample;
}
static getFormatMultiply(format) {
switch (format) {
case 8: return 1;
case 16: return 2;
}
throw new Error("Unknown or unsupported sample format id " + format);
}
static getFormatFunctionFromId(format) {
switch (format) {
case 8: return Furnace8bitSample.fromBuffer;
case 16: return Furnace16bitSample.fromBuffer;
}
throw new Error("Unknown or unsupported sample format id " + format);
}
writeToBuffer(helper, version) {
if (version >= 102) {
this.writeToBufferSMP2(helper);
}
else {
this.writeToBufferSMPL(helper, version);
}
}
writeToBufferSMP2(helper) {
var _a, _b;
const _begin = helper.getPosition(8);
helper.writeString(FurnaceSample.magic2, "ascii", false);
helper.skipBytes(4);
helper.writeString(this.name, "utf-8", true);
helper.writeUInt32LE(this.data.entries / FurnaceSample.getFormatMultiply(this.data.formatId));
helper.writeUInt32LE(this.compatRate);
helper.writeUInt32LE(this.c4Rate);
helper.writeUInt8(this.data.formatId);
helper.skipBytes(3);
helper.writeUInt32LE((_a = this.loopStart) !== null && _a !== void 0 ? _a : 0xFFFFFFFF);
helper.writeUInt32LE((_b = this.loopEnd) !== null && _b !== void 0 ? _b : 0xFFFFFFFF);
helper.writeUInt32LE(this.precense[0]);
helper.writeUInt32LE(this.precense[1]);
helper.writeUInt32LE(this.precense[2]);
helper.writeUInt32LE(this.precense[3]);
helper.writeBuffer(this.data.rawBuffer, 0, this.data.rawBuffer.length);
helper.writeUInt32LE(helper.getPosition() - _begin, _begin - 4);
}
writeToBufferSMPL(helper, version) {
var _a, _b, _c;
const _begin = helper.getPosition(8);
helper.writeString(FurnaceSample.magic, "ascii", false);
helper.skipBytes(4);
helper.writeString(this.name, "utf-8", true);
helper.writeUInt32LE(this.data.entries / (version < 58 ? 2 : FurnaceSample.getFormatMultiply(this.data.formatId)));
helper.writeUInt32LE(this.compatRate);
helper.writeInt16LE((_a = this.volume) !== null && _a !== void 0 ? _a : 0);
helper.writeInt16LE((_b = this.pitch) !== null && _b !== void 0 ? _b : 0);
helper.writeUInt8(this.data.formatId);
helper.skipBytes(1);
helper.writeUInt16LE(this.c4Rate);
helper.writeUInt32LE((_c = this.loopStart) !== null && _c !== void 0 ? _c : 0xFFFFFFFF);
helper.writeBuffer(this.data.rawBuffer, 0, this.data.rawBuffer.length);
helper.writeUInt32LE(helper.getPosition() - _begin, _begin - 4);
}
}
exports.FurnaceSample = FurnaceSample;
FurnaceSample.magic = "SMPL";
FurnaceSample.magic2 = "SMP2";
class Furnace8bitSample {
constructor() {
this.formatName = "8-bit PCM";
this.formatId = 8;
this.entries = 0;
}
static create() {
const format = new Furnace8bitSample();
format.rawBuffer = Buffer.alloc(0);
return format;
}
static fromBuffer(buffer, length) {
const format = new Furnace8bitSample();
format.rawBuffer = buffer;
format.entries = length;
return format;
}
convertToArray() {
const array = new Int16Array(this.entries);
for (let i = 0; i < this.entries; i++) {
array[i] = this.rawBuffer.readInt8(i) << 8;
}
return array;
}
convertFromArray(array) {
this.entries = array.length;
this.rawBuffer = Buffer.alloc(this.entries);
for (let i = 0; i < this.entries; i++) {
this.rawBuffer.writeInt8(array[i] >> 8, i);
}
}
}
exports.Furnace8bitSample = Furnace8bitSample;
class Furnace16bitSample {
constructor() {
this.formatName = "16-bit PCM";
this.formatId = 16;
this.entries = 0;
}
static create() {
const format = new Furnace16bitSample();
format.rawBuffer = Buffer.alloc(0);
return format;
}
static fromBuffer(buffer, length) {
const format = new Furnace16bitSample();
format.rawBuffer = buffer;
format.entries = length;
return format;
}
convertToArray() {
const array = new Int16Array(this.entries);
for (let i = 0; i < this.entries; i++) {
array[i] = this.rawBuffer.readInt16LE(i * 2);
}
return array;
}
convertFromArray(array) {
this.entries = array.length;
this.rawBuffer = Buffer.alloc(this.entries * 2);
for (let i = 0; i < this.entries; i++) {
this.rawBuffer.writeInt16LE(array[i], i * 2);
}
}
}
exports.Furnace16bitSample = Furnace16bitSample;