furnace-module-interface
Version:
An interface for loading, processing and saving furnace modules in an object-oriented manner. Fully typed via TypeScript.
681 lines (680 loc) • 38.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FurnaceInstrumentViewAmiga = exports.FurnaceAmigaModeEnum = exports.FurnaceInstrumentViewOpOPNOPM = exports.FurnaceInstrumentViewOPNOPM = exports.FurnaceInstrumentViewStandard = exports.FurnaceInstrument = exports.FurnaceInstrumentTypeEnum = void 0;
const defaults_1 = require("./defaults");
const macros_1 = require("./macros");
var FurnaceInstrumentTypeEnum;
(function (FurnaceInstrumentTypeEnum) {
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["Standard"] = 0] = "Standard";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["OPMOPN"] = 1] = "OPMOPN";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["GameBoy"] = 2] = "GameBoy";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["C64"] = 3] = "C64";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["Amiga"] = 4] = "Amiga";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["PCEngine"] = 5] = "PCEngine";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["AY38910"] = 6] = "AY38910";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["AY8930"] = 7] = "AY8930";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["TIA"] = 8] = "TIA";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["SAA1099"] = 9] = "SAA1099";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["VIC"] = 10] = "VIC";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["PET"] = 11] = "PET";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["VRC6"] = 12] = "VRC6";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["OPLL"] = 13] = "OPLL";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["OPL"] = 14] = "OPL";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["FDS"] = 15] = "FDS";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["VirtualBoy"] = 16] = "VirtualBoy";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["Namco163"] = 17] = "Namco163";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["SCC"] = 18] = "SCC";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["OPZ"] = 19] = "OPZ";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["POKEY"] = 20] = "POKEY";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["PCSpeaker"] = 21] = "PCSpeaker";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["WonderSwan"] = 22] = "WonderSwan";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["Lynx"] = 23] = "Lynx";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["VERA"] = 24] = "VERA";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["X1010"] = 25] = "X1010";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["VRC6Saw"] = 26] = "VRC6Saw";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["E5506"] = 27] = "E5506";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["MultiPCM"] = 28] = "MultiPCM";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["SNES"] = 29] = "SNES";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["SoundUnit"] = 30] = "SoundUnit";
FurnaceInstrumentTypeEnum[FurnaceInstrumentTypeEnum["NamcoWSG"] = 31] = "NamcoWSG";
})(FurnaceInstrumentTypeEnum = exports.FurnaceInstrumentTypeEnum || (exports.FurnaceInstrumentTypeEnum = {}));
class FurnaceInstrument {
constructor() {
var _a;
this.version = defaults_1.defaults.version;
this.name = defaults_1.defaults.instrumentName;
this.type = FurnaceInstrumentTypeEnum.Standard;
this.vars = {
fmInsData: Array.from(defaults_1.defaults.fmInsData),
fmInsOpData: Array.from(defaults_1.defaults.fmInsOpData),
gbInsData: Array.from(defaults_1.defaults.gbInsData),
gbExtraInsData: Array.from(defaults_1.defaults.gbExtraInsData),
c64InsData: Array.from(defaults_1.defaults.c64InsData),
amigaInsData: Array.from(defaults_1.defaults.amigaInsData),
oplDrumsModeData: Array.from(defaults_1.defaults.oplDrumsModeData),
namco163InsData: Array.from(defaults_1.defaults.namco163InsData),
fdsInsData: Array.from(defaults_1.defaults.fdsInsData),
fdsModTable: Array.from(defaults_1.defaults.fdsModTable),
opzInsData: Array.from(defaults_1.defaults.opzInsData),
wavetableSynthInsData: Array.from(defaults_1.defaults.wavetableSynthInsData),
multipcmInsData: Array.from(defaults_1.defaults.multipcmInsData),
tsuInsData: Array.from(defaults_1.defaults.tsuInsData),
gbEnvSeq: Array.from(defaults_1.defaults.gbEnvSeq),
sampleMap: [],
volumeMacro: new macros_1.FurnaceMacroWithHeight(),
arpeggioMacro: new macros_1.FurnaceArpeggioMacro(),
dutyMacro: new macros_1.FurnaceMacroWithHeight(),
waveMacro: new macros_1.FurnaceMacroWithHeight(),
pitchMacro: new macros_1.FurnaceGenericMacro(),
algorithmMacro: new macros_1.FurnaceGenericMacro(),
feedbackMacro: new macros_1.FurnaceGenericMacro(),
fmsMacro: new macros_1.FurnaceGenericMacro(),
amsMacro: new macros_1.FurnaceGenericMacro(),
leftPanMacro: new macros_1.FurnaceGenericMacro(),
rightPanMacro: new macros_1.FurnaceGenericMacro(),
phaseResetMacro: new macros_1.FurnaceGenericMacro(),
extra1Macro: new macros_1.FurnaceGenericMacro(),
extra2Macro: new macros_1.FurnaceGenericMacro(),
extra3Macro: new macros_1.FurnaceGenericMacro(),
extra4Macro: new macros_1.FurnaceGenericMacro(),
extra5Macro: new macros_1.FurnaceGenericMacro(),
extra6Macro: new macros_1.FurnaceGenericMacro(),
extra7Macro: new macros_1.FurnaceGenericMacro(),
extra8Macro: new macros_1.FurnaceGenericMacro(),
amplitudeModulationMacro: [new macros_1.FurnaceOperatorMacro(1), new macros_1.FurnaceOperatorMacro(3), new macros_1.FurnaceOperatorMacro(2), new macros_1.FurnaceOperatorMacro(4),],
attackRateMaco: [new macros_1.FurnaceOperatorMacro(1), new macros_1.FurnaceOperatorMacro(3), new macros_1.FurnaceOperatorMacro(2), new macros_1.FurnaceOperatorMacro(4),],
decay1RateMacro: [new macros_1.FurnaceOperatorMacro(1), new macros_1.FurnaceOperatorMacro(3), new macros_1.FurnaceOperatorMacro(2), new macros_1.FurnaceOperatorMacro(4),],
multipleMacro: [new macros_1.FurnaceOperatorMacro(1), new macros_1.FurnaceOperatorMacro(3), new macros_1.FurnaceOperatorMacro(2), new macros_1.FurnaceOperatorMacro(4),],
releaseRateMacro: [new macros_1.FurnaceOperatorMacro(1), new macros_1.FurnaceOperatorMacro(3), new macros_1.FurnaceOperatorMacro(2), new macros_1.FurnaceOperatorMacro(4),],
decay2LevelMacro: [new macros_1.FurnaceOperatorMacro(1), new macros_1.FurnaceOperatorMacro(3), new macros_1.FurnaceOperatorMacro(2), new macros_1.FurnaceOperatorMacro(4),],
totalLevelMacro: [new macros_1.FurnaceOperatorMacro(1), new macros_1.FurnaceOperatorMacro(3), new macros_1.FurnaceOperatorMacro(2), new macros_1.FurnaceOperatorMacro(4),],
detune2Macro: [new macros_1.FurnaceOperatorMacro(1), new macros_1.FurnaceOperatorMacro(3), new macros_1.FurnaceOperatorMacro(2), new macros_1.FurnaceOperatorMacro(4),],
rateScaleMacro: [new macros_1.FurnaceOperatorMacro(1), new macros_1.FurnaceOperatorMacro(3), new macros_1.FurnaceOperatorMacro(2), new macros_1.FurnaceOperatorMacro(4),],
detuneMacro: [new macros_1.FurnaceOperatorMacro(1), new macros_1.FurnaceOperatorMacro(3), new macros_1.FurnaceOperatorMacro(2), new macros_1.FurnaceOperatorMacro(4),],
decay2RateMacro: [new macros_1.FurnaceOperatorMacro(1), new macros_1.FurnaceOperatorMacro(3), new macros_1.FurnaceOperatorMacro(2), new macros_1.FurnaceOperatorMacro(4),],
ssgegMacro: [new macros_1.FurnaceOperatorMacro(1), new macros_1.FurnaceOperatorMacro(3), new macros_1.FurnaceOperatorMacro(2), new macros_1.FurnaceOperatorMacro(4),],
_damMacro: [new macros_1.FurnaceOperatorMacro(1), new macros_1.FurnaceOperatorMacro(3), new macros_1.FurnaceOperatorMacro(2), new macros_1.FurnaceOperatorMacro(4),],
_dvbMacro: [new macros_1.FurnaceOperatorMacro(1), new macros_1.FurnaceOperatorMacro(3), new macros_1.FurnaceOperatorMacro(2), new macros_1.FurnaceOperatorMacro(4),],
_egtMacro: [new macros_1.FurnaceOperatorMacro(1), new macros_1.FurnaceOperatorMacro(3), new macros_1.FurnaceOperatorMacro(2), new macros_1.FurnaceOperatorMacro(4),],
_kslMacro: [new macros_1.FurnaceOperatorMacro(1), new macros_1.FurnaceOperatorMacro(3), new macros_1.FurnaceOperatorMacro(2), new macros_1.FurnaceOperatorMacro(4),],
_susMacro: [new macros_1.FurnaceOperatorMacro(1), new macros_1.FurnaceOperatorMacro(3), new macros_1.FurnaceOperatorMacro(2), new macros_1.FurnaceOperatorMacro(4),],
_vibMacro: [new macros_1.FurnaceOperatorMacro(1), new macros_1.FurnaceOperatorMacro(3), new macros_1.FurnaceOperatorMacro(2), new macros_1.FurnaceOperatorMacro(4),],
_wsMacro: [new macros_1.FurnaceOperatorMacro(1), new macros_1.FurnaceOperatorMacro(3), new macros_1.FurnaceOperatorMacro(2), new macros_1.FurnaceOperatorMacro(4),],
_ksrMacro: [new macros_1.FurnaceOperatorMacro(1), new macros_1.FurnaceOperatorMacro(3), new macros_1.FurnaceOperatorMacro(2), new macros_1.FurnaceOperatorMacro(4),],
};
for (let i = 0; i < 120; i++) {
(_a = this.vars.sampleMap) === null || _a === void 0 ? void 0 : _a.push({ frequency: 0, sample: 0, });
}
}
static create() {
return new FurnaceInstrument();
}
static fromHelper(helper) {
const mod = FurnaceInstrument.create();
if (FurnaceInstrument.magic !== helper.getASCII(4)) {
throw new Error("Expected format magic string \"" + FurnaceInstrument.magic + "\" when loading an instrument block.");
}
helper.skipBytes(4);
mod.version = helper.readUInt16LE();
mod.type = helper.readUInt8();
helper.skipBytes(1);
mod.name = helper.readString("utf-8");
mod.vars.fmInsData = [...helper.readBuffer(defaults_1.defaults.fmInsData.length),];
mod.vars.fmInsOpData = [...helper.readBuffer(defaults_1.defaults.fmInsOpData.length),];
mod.vars.gbInsData = [...helper.readBuffer(defaults_1.defaults.gbInsData.length),];
mod.vars.c64InsData[0] = helper.readUInt8();
mod.vars.c64InsData[1] = helper.readUInt8();
mod.vars.c64InsData[2] = helper.readUInt8();
mod.vars.c64InsData[3] = helper.readUInt8();
mod.vars.c64InsData[4] = helper.readUInt8();
mod.vars.c64InsData[5] = helper.readUInt8();
mod.vars.c64InsData[6] = helper.readUInt8();
mod.vars.c64InsData[7] = helper.readUInt8();
mod.vars.c64InsData[8] = helper.readUInt16LE();
mod.vars.c64InsData[9] = helper.readUInt8();
mod.vars.c64InsData[10] = helper.readUInt8();
mod.vars.c64InsData[11] = helper.readUInt8();
mod.vars.c64InsData[12] = helper.readUInt8();
mod.vars.c64InsData[13] = helper.readUInt8();
mod.vars.c64InsData[14] = helper.readUInt8();
mod.vars.c64InsData[15] = helper.readUInt8();
mod.vars.c64InsData[16] = helper.readUInt8();
mod.vars.c64InsData[17] = helper.readUInt8();
mod.vars.c64InsData[18] = helper.readUInt8();
mod.vars.c64InsData[19] = helper.readUInt16LE();
mod.vars.c64InsData[20] = helper.readUInt8();
mod.vars.c64InsData[21] = helper.readUInt8();
mod.vars.amigaInsData[0] = helper.readUInt16LE();
mod.vars.amigaInsData[2] = helper.readUInt8();
mod.vars.amigaInsData[3] = helper.readUInt8();
helper.skipBytes(12);
const getLoopReleaseValue = () => {
const val = helper.readUInt32LE();
if (val !== 0xFFFFFFFF) {
return val;
}
return null;
};
const getMacroOpen = () => {
return helper.readUInt8() !== 0;
};
const loadMacroData = (count) => {
const data = [];
for (let i = 0; i < count; i++) {
data.push(helper.readInt32LE());
}
return data;
};
const loadMacroByteData = (count) => {
const data = [];
for (let i = 0; i < count; i++) {
data.push(helper.readUInt8());
}
return data;
};
const lengths = {};
mainInsMacroNames.forEach((prop) => lengths[prop] = helper.readUInt32LE());
mainInsMacroNames.forEach((prop) => mod.vars[prop].loop = getLoopReleaseValue());
mod.vars.arpeggioMacro.isAbsolute = helper.readUInt8() !== 0;
helper.skipBytes(3);
if (mod.version < 17) {
mod.vars.pitchMacro = null;
mod.vars.extra1Macro = null;
mod.vars.extra2Macro = null;
mod.vars.extra3Macro = null;
}
if (mod.version !== 15 && mod.version !== 16) {
mod.vars.volumeMacro.height = null;
mod.vars.dutyMacro.height = null;
mod.vars.waveMacro.height = null;
}
if (mod.version < 31) {
mod.vars.arpeggioMacro.valueOffset = 12;
}
mainInsMacroNames.forEach((prop) => {
if (mod.vars[prop]) {
mod.vars[prop].data = loadMacroData(lengths[prop]);
}
});
if (mod.version < 29) {
fmInsMacroNames.forEach((prop) => mod.vars[prop] = null);
fmOpInsMacroNames.forEach((prop) => mod.vars[prop] = null);
}
else {
fmInsMacroNames.forEach((prop) => lengths[prop] = helper.readUInt32LE());
fmInsMacroNames.forEach((prop) => mod.vars[prop].loop = getLoopReleaseValue());
mainInsMacroNames.forEach((prop) => mod.vars[prop].open = getMacroOpen());
fmInsMacroNames.forEach((prop) => mod.vars[prop].open = getMacroOpen());
fmInsMacroNames.forEach((prop) => mod.vars[prop].data = loadMacroData(lengths[prop]));
for (let i = 0; i < 4; i++) {
fmOpInsMacroNames.forEach((prop) => lengths[prop + "_" + i] = helper.readUInt32LE());
fmOpInsMacroNames.forEach((prop) => mod.vars[prop][i].loop = getLoopReleaseValue());
fmOpInsMacroNames.forEach((prop) => mod.vars[prop][i].open = getMacroOpen());
}
for (let i = 0; i < 4; i++) {
fmOpInsMacroNames.forEach((prop) => mod.vars[prop][i].data = loadMacroByteData(lengths[prop + "_" + i]));
}
}
if (mod.version >= 44) {
mainInsMacroNames.forEach((prop) => mod.vars[prop].release = getLoopReleaseValue());
fmInsMacroNames.forEach((prop) => mod.vars[prop].release = getLoopReleaseValue());
for (let i = 0; i < 4; i++) {
fmOpInsMacroNames.forEach((prop) => mod.vars[prop][i].release = getLoopReleaseValue());
}
}
if (mod.version < 61) {
extOpInsMacroNames.forEach((prop) => mod.vars[prop] = null);
}
else {
for (let i = 0; i < 4; i++) {
extOpInsMacroNames.forEach((prop) => lengths[prop + "_" + i] = helper.readUInt32LE());
extOpInsMacroNames.forEach((prop) => mod.vars[prop][i].loop = getLoopReleaseValue());
extOpInsMacroNames.forEach((prop) => mod.vars[prop][i].release = getLoopReleaseValue());
extOpInsMacroNames.forEach((prop) => mod.vars[prop][i].open = getMacroOpen());
}
for (let i = 0; i < 4; i++) {
extOpInsMacroNames.forEach((prop) => mod.vars[prop][i].data = loadMacroByteData(lengths[prop + "_" + i]));
}
}
if (mod.version >= 63) {
mod.vars.oplDrumsModeData[0] = helper.readUInt8();
helper.skipBytes(1);
mod.vars.oplDrumsModeData[1] = helper.readUInt16LE();
mod.vars.oplDrumsModeData[2] = helper.readUInt16LE();
mod.vars.oplDrumsModeData[3] = helper.readUInt16LE();
}
if (mod.version < 67 || helper.readUInt8() === 0) {
mod.vars.sampleMap = null;
}
else {
for (let i = 0; i < 120; i++) {
mod.vars.sampleMap[i].frequency = helper.readUInt32LE();
}
for (let i = 0; i < 120; i++) {
mod.vars.sampleMap[i].sample = helper.readUInt16LE();
}
}
if (mod.version >= 73) {
mod.vars.namco163InsData[0] = helper.readUInt32LE();
mod.vars.namco163InsData[1] = helper.readUInt8();
mod.vars.namco163InsData[2] = helper.readUInt8();
mod.vars.namco163InsData[3] = helper.readUInt8();
helper.skipBytes(1);
}
if (mod.version < 76) {
moreInsMacroNames.forEach((prop) => mod.vars[prop] = null);
}
else {
moreInsMacroNames.forEach((prop) => lengths[prop] = helper.readUInt32LE());
moreInsMacroNames.forEach((prop) => mod.vars[prop].loop = getLoopReleaseValue());
moreInsMacroNames.forEach((prop) => mod.vars[prop].release = getLoopReleaseValue());
moreInsMacroNames.forEach((prop) => mod.vars[prop].open = getMacroOpen());
moreInsMacroNames.forEach((prop) => mod.vars[prop].data = loadMacroData(lengths[prop]));
mod.vars.fdsInsData[0] = helper.readUInt32LE();
mod.vars.fdsInsData[1] = helper.readUInt32LE();
mod.vars.fdsInsData[2] = helper.readUInt8();
helper.skipBytes(3);
mod.vars.fdsModTable = [...helper.readBuffer(32),];
}
if (mod.version >= 77) {
mod.vars.opzInsData[0] = helper.readUInt8();
mod.vars.opzInsData[1] = helper.readUInt8();
}
if (mod.version >= 79) {
mod.vars.wavetableSynthInsData[0] = helper.readUInt32LE();
mod.vars.wavetableSynthInsData[1] = helper.readUInt32LE();
mod.vars.wavetableSynthInsData[2] = helper.readUInt8();
mod.vars.wavetableSynthInsData[3] = helper.readUInt8();
mod.vars.wavetableSynthInsData[4] = helper.readUInt8();
mod.vars.wavetableSynthInsData[5] = helper.readUInt8();
mod.vars.wavetableSynthInsData[6] = helper.readUInt8();
mod.vars.wavetableSynthInsData[7] = helper.readUInt8();
mod.vars.wavetableSynthInsData[8] = helper.readUInt8();
mod.vars.wavetableSynthInsData[9] = helper.readUInt8();
mod.vars.wavetableSynthInsData[10] = helper.readUInt8();
}
if (mod.version >= 84) {
mainInsMacroNames.filter((v) => !v.includes("arpeggio")).forEach((prop) => mod.vars[prop].mode = helper.readUInt8());
fmInsMacroNames.forEach((prop) => mod.vars[prop].mode = helper.readUInt8());
moreInsMacroNames.forEach((prop) => mod.vars[prop].mode = helper.readUInt8());
}
if (mod.version >= 89) {
mod.vars.c64InsData[22] = helper.readUInt8();
}
if (mod.version >= 93) {
mod.vars.multipcmInsData = [...helper.readBuffer(defaults_1.defaults.multipcmInsData.length),];
}
if (mod.version >= 104) {
mod.vars.tsuInsData = [...helper.readBuffer(defaults_1.defaults.tsuInsData.length),];
}
if (mod.version >= 105) {
const length = helper.readUInt8() * 3;
mod.vars.gbEnvSeq = [...helper.readBuffer(length),];
}
if (mod.version >= 106) {
mod.vars.gbExtraInsData = [...helper.readBuffer(defaults_1.defaults.gbExtraInsData.length),];
}
return mod;
}
writeToBuffer(helper) {
var _a, _b, _c;
const _begin = helper.getPosition(8);
helper.writeString(FurnaceInstrument.magic, "ascii", false);
helper.skipBytes(4);
helper.writeInt16LE(this.version);
helper.writeUInt8(this.type);
helper.skipBytes(1);
helper.writeString(this.name, "utf-8", true);
helper.writeBuffer(Buffer.from(this.vars.fmInsData), 0, this.vars.fmInsData.length);
helper.writeBuffer(Buffer.from(this.vars.fmInsOpData), 0, this.vars.fmInsOpData.length);
helper.writeBuffer(Buffer.from(this.vars.gbInsData), 0, this.vars.gbInsData.length);
helper.writeUInt8(this.vars.c64InsData[0]);
helper.writeUInt8(this.vars.c64InsData[1]);
helper.writeUInt8(this.vars.c64InsData[2]);
helper.writeUInt8(this.vars.c64InsData[3]);
helper.writeUInt8(this.vars.c64InsData[4]);
helper.writeUInt8(this.vars.c64InsData[5]);
helper.writeUInt8(this.vars.c64InsData[6]);
helper.writeUInt8(this.vars.c64InsData[7]);
helper.writeUInt16LE(this.vars.c64InsData[8]);
helper.writeUInt8(this.vars.c64InsData[9]);
helper.writeUInt8(this.vars.c64InsData[10]);
helper.writeUInt8(this.vars.c64InsData[11]);
helper.writeUInt8(this.vars.c64InsData[12]);
helper.writeUInt8(this.vars.c64InsData[13]);
helper.writeUInt8(this.vars.c64InsData[14]);
helper.writeUInt8(this.vars.c64InsData[15]);
helper.writeUInt8(this.vars.c64InsData[16]);
helper.writeUInt8(this.vars.c64InsData[17]);
helper.writeUInt8(this.vars.c64InsData[18]);
helper.writeUInt16LE(this.vars.c64InsData[19]);
helper.writeUInt8(this.vars.c64InsData[20]);
helper.writeUInt8(this.vars.c64InsData[21]);
helper.writeUInt16LE(this.vars.amigaInsData[0]);
helper.writeUInt8(this.vars.amigaInsData[2]);
helper.writeUInt8(this.vars.amigaInsData[3]);
helper.skipBytes(12);
const writeMacroData = (macro) => {
if (macro) {
for (let i = 0; i < macro.data.length; i++) {
helper.writeInt32LE(macro.data[i]);
}
}
};
mainInsMacroNames.forEach((prop) => helper.writeUInt32LE(this.vars[prop].data.length));
mainInsMacroNames.forEach((prop) => { var _a; return helper.writeUInt32LE((_a = this.vars[prop].loop) !== null && _a !== void 0 ? _a : 0xFFFFFFFF); });
helper.writeUInt8(this.vars.arpeggioMacro.isAbsolute ? 1 : 0);
helper.writeUInt8((_a = this.vars.volumeMacro.height) !== null && _a !== void 0 ? _a : 0);
helper.writeUInt8((_b = this.vars.dutyMacro.height) !== null && _b !== void 0 ? _b : 0);
helper.writeUInt8((_c = this.vars.waveMacro.height) !== null && _c !== void 0 ? _c : 0);
mainInsMacroNames.forEach((prop) => writeMacroData(this.vars[prop]));
if (this.version >= 29) {
fmInsMacroNames.forEach((prop) => helper.writeUInt32LE(this.vars[prop].data.length));
fmInsMacroNames.forEach((prop) => { var _a; return helper.writeUInt32LE((_a = this.vars[prop].loop) !== null && _a !== void 0 ? _a : 0xFFFFFFFF); });
mainInsMacroNames.forEach((prop) => helper.writeUInt8(this.vars[prop].open ? 1 : 0));
fmInsMacroNames.forEach((prop) => helper.writeUInt8(this.vars[prop].open ? 1 : 0));
fmInsMacroNames.forEach((prop) => writeMacroData(this.vars[prop]));
for (let i = 0; i < 4; i++) {
fmOpInsMacroNames.forEach((prop) => helper.writeUInt32LE(this.vars[prop][i].data.length));
fmOpInsMacroNames.forEach((prop) => { var _a; return helper.writeUInt32LE((_a = this.vars[prop][i].loop) !== null && _a !== void 0 ? _a : 0xFFFFFFFF); });
fmOpInsMacroNames.forEach((prop) => helper.writeUInt8(this.vars[prop][i].open ? 1 : 0));
}
for (let i = 0; i < 4; i++) {
fmOpInsMacroNames.forEach((prop) => writeMacroData(this.vars[prop][i]));
}
}
if (this.version >= 44) {
mainInsMacroNames.forEach((prop) => { var _a; return helper.writeUInt32LE((_a = this.vars[prop].release) !== null && _a !== void 0 ? _a : 0xFFFFFFFF); });
fmInsMacroNames.forEach((prop) => { var _a; return helper.writeUInt32LE((_a = this.vars[prop].release) !== null && _a !== void 0 ? _a : 0xFFFFFFFF); });
for (let i = 0; i < 4; i++) {
fmOpInsMacroNames.forEach((prop) => { var _a; return helper.writeUInt32LE((_a = this.vars[prop][i].release) !== null && _a !== void 0 ? _a : 0xFFFFFFFF); });
}
}
if (this.version >= 61) {
for (let i = 0; i < 4; i++) {
extOpInsMacroNames.forEach((prop) => helper.writeUInt32LE(this.vars[prop][i].data.length));
extOpInsMacroNames.forEach((prop) => { var _a; return helper.writeUInt32LE((_a = this.vars[prop][i].loop) !== null && _a !== void 0 ? _a : 0xFFFFFFFF); });
extOpInsMacroNames.forEach((prop) => { var _a; return helper.writeUInt32LE((_a = this.vars[prop][i].release) !== null && _a !== void 0 ? _a : 0xFFFFFFFF); });
extOpInsMacroNames.forEach((prop) => helper.writeUInt8(this.vars[prop][i].open ? 1 : 0));
}
for (let i = 0; i < 4; i++) {
extOpInsMacroNames.forEach((prop) => writeMacroData(this.vars[prop][i]));
}
}
if (this.version >= 63) {
helper.writeUInt8(this.vars.oplDrumsModeData[0]);
helper.skipBytes(1);
helper.writeUInt16LE(this.vars.oplDrumsModeData[1]);
helper.writeUInt16LE(this.vars.oplDrumsModeData[2]);
helper.writeUInt16LE(this.vars.oplDrumsModeData[3]);
}
if (this.version < 67 || this.vars.sampleMap === null) {
helper.writeUInt8(0);
}
else {
helper.writeUInt8(1);
for (let i = 0; i < 120; i++) {
helper.writeUInt32LE(this.vars.sampleMap[i].frequency);
}
for (let i = 0; i < 120; i++) {
helper.writeUInt16LE(this.vars.sampleMap[i].sample);
}
}
if (this.version >= 73) {
helper.writeUInt32LE(this.vars.namco163InsData[0]);
helper.writeUInt8(this.vars.namco163InsData[1]);
helper.writeUInt8(this.vars.namco163InsData[2]);
helper.writeUInt8(this.vars.namco163InsData[3]);
helper.skipBytes(1);
}
if (this.version >= 76) {
moreInsMacroNames.forEach((prop) => helper.writeUInt32LE(this.vars[prop].data.length));
moreInsMacroNames.forEach((prop) => { var _a; return helper.writeUInt32LE((_a = this.vars[prop].loop) !== null && _a !== void 0 ? _a : 0xFFFFFFFF); });
moreInsMacroNames.forEach((prop) => { var _a; return helper.writeUInt32LE((_a = this.vars[prop].release) !== null && _a !== void 0 ? _a : 0xFFFFFFFF); });
moreInsMacroNames.forEach((prop) => helper.writeUInt8(this.vars[prop].open ? 1 : 0));
moreInsMacroNames.forEach((prop) => writeMacroData(this.vars[prop]));
helper.writeUInt32LE(this.vars.fdsInsData[0]);
helper.writeUInt32LE(this.vars.fdsInsData[1]);
helper.writeUInt8(this.vars.fdsInsData[2]);
helper.skipBytes(3);
helper.writeBuffer(Buffer.from(this.vars.fdsModTable), 0, this.vars.fdsModTable.length);
}
if (this.version >= 77) {
helper.writeUInt8(this.vars.opzInsData[0]);
helper.writeUInt8(this.vars.opzInsData[1]);
}
if (this.version >= 79) {
helper.writeUInt32LE(this.vars.wavetableSynthInsData[0]);
helper.writeUInt32LE(this.vars.wavetableSynthInsData[1]);
helper.writeUInt8(this.vars.wavetableSynthInsData[2]);
helper.writeUInt8(this.vars.wavetableSynthInsData[3]);
helper.writeUInt8(this.vars.wavetableSynthInsData[4]);
helper.writeUInt8(this.vars.wavetableSynthInsData[5]);
helper.writeUInt8(this.vars.wavetableSynthInsData[6]);
helper.writeUInt8(this.vars.wavetableSynthInsData[7]);
helper.writeUInt8(this.vars.wavetableSynthInsData[8]);
helper.writeUInt8(this.vars.wavetableSynthInsData[9]);
helper.writeUInt8(this.vars.wavetableSynthInsData[10]);
}
if (this.version >= 84) {
mainInsMacroNames.filter((v) => !v.includes("arpeggio")).forEach((prop) => { var _a; return helper.writeUInt8((_a = this.vars[prop].mode) !== null && _a !== void 0 ? _a : 0); });
fmInsMacroNames.forEach((prop) => { var _a; return helper.writeUInt8((_a = this.vars[prop].mode) !== null && _a !== void 0 ? _a : 0); });
moreInsMacroNames.forEach((prop) => { var _a; return helper.writeUInt8((_a = this.vars[prop].mode) !== null && _a !== void 0 ? _a : 0); });
}
if (this.version >= 89) {
helper.writeUInt8(this.vars.c64InsData[22]);
}
if (this.version >= 93) {
helper.writeBuffer(Buffer.from(this.vars.multipcmInsData), 0, this.vars.multipcmInsData.length);
}
if (this.version >= 104) {
helper.writeBuffer(Buffer.from(this.vars.tsuInsData), 0, this.vars.tsuInsData.length);
}
if (this.version >= 105) {
helper.writeUInt8(this.vars.gbEnvSeq.length / 3);
helper.writeBuffer(Buffer.from(this.vars.gbEnvSeq), 0, this.vars.gbEnvSeq.length);
}
if (this.version >= 106) {
helper.writeBuffer(Buffer.from(this.vars.gbExtraInsData), 0, this.vars.gbExtraInsData.length);
}
helper.writeUInt32LE(helper.getPosition() - _begin, _begin - 4);
}
getView(type) {
var _a;
switch (type) {
case FurnaceInstrumentTypeEnum.Standard:
return new FurnaceInstrumentViewStandard(this.vars);
case FurnaceInstrumentTypeEnum.OPMOPN:
return new FurnaceInstrumentViewOPNOPM(this.vars);
case FurnaceInstrumentTypeEnum.Amiga:
return new FurnaceInstrumentViewAmiga(this.vars);
}
throw new Error("Unknown or unsupported instrument type id " + ((_a = FurnaceInstrumentTypeEnum[type]) !== null && _a !== void 0 ? _a : type));
}
getVersion() {
return this.version;
}
}
exports.FurnaceInstrument = FurnaceInstrument;
FurnaceInstrument.magic = "INST";
const mainInsMacroNames = [
"volumeMacro",
"arpeggioMacro",
"dutyMacro",
"waveMacro",
"pitchMacro",
"extra1Macro",
"extra2Macro",
"extra3Macro",
];
const moreInsMacroNames = [
"leftPanMacro",
"rightPanMacro",
"phaseResetMacro",
"extra4Macro",
"extra5Macro",
"extra6Macro",
"extra7Macro",
"extra8Macro",
];
const fmInsMacroNames = [
"algorithmMacro",
"feedbackMacro",
"fmsMacro",
"amsMacro",
];
const fmOpInsMacroNames = [
"amplitudeModulationMacro",
"attackRateMaco",
"decay1RateMacro",
"multipleMacro",
"releaseRateMacro",
"decay2LevelMacro",
"totalLevelMacro",
"detune2Macro",
"rateScaleMacro",
"detuneMacro",
"decay2RateMacro",
"ssgegMacro",
];
const extOpInsMacroNames = [
"_damMacro",
"_dvbMacro",
"_egtMacro",
"_kslMacro",
"_susMacro",
"_vibMacro",
"_wsMacro",
"_ksrMacro",
];
class FurnaceInstrumentViewStandard {
constructor(vars) {
this.vars = vars;
this.type = FurnaceInstrumentTypeEnum.Standard;
}
get volumeMacro() { return this.vars.volumeMacro; }
get noiseModeMacro() { return this.vars.dutyMacro; }
get arpeggioMacro() { return this.vars.arpeggioMacro; }
get pitchMacro() { return this.vars.pitchMacro; }
get phaseResetMacro() { return this.vars.phaseResetMacro; }
}
exports.FurnaceInstrumentViewStandard = FurnaceInstrumentViewStandard;
class FurnaceInstrumentViewOPNOPM {
constructor(vars) {
this.vars = vars;
this.type = FurnaceInstrumentTypeEnum.OPMOPN;
this.operators = [
new FurnaceInstrumentViewOpOPNOPM(32 * 0, 0, vars),
new FurnaceInstrumentViewOpOPNOPM(32 * 1, 1, vars),
new FurnaceInstrumentViewOpOPNOPM(32 * 2, 2, vars),
new FurnaceInstrumentViewOpOPNOPM(32 * 3, 3, vars),
];
}
get algorithm() { return this.vars.fmInsData[0]; }
set algorithm(value) { this.vars.fmInsData[0] = value; }
get feedback() { return this.vars.fmInsData[1]; }
set feedback(value) { this.vars.fmInsData[1] = value; }
get fms() { return this.vars.fmInsData[2]; }
set fms(value) { this.vars.fmInsData[2] = value; }
get ams() { return this.vars.fmInsData[3]; }
set ams(value) { this.vars.fmInsData[3] = value; }
get operatorCount() { return this.vars.fmInsData[4]; }
set operatorCount(value) { this.vars.fmInsData[4] = value; }
get volumeMacro() { return this.vars.volumeMacro; }
get arpeggioMacro() { return this.vars.arpeggioMacro; }
get pitchMacro() { return this.vars.pitchMacro; }
get algorithmMacro() { return this.vars.algorithmMacro; }
get feedbackMacro() { return this.vars.feedbackMacro; }
get fmsMacro() { return this.vars.fmsMacro; }
get amsMacro() { return this.vars.amsMacro; }
get hardPanMacro() { return this.vars.leftPanMacro; }
get phaseResetMacro() { return this.vars.phaseResetMacro; }
}
exports.FurnaceInstrumentViewOPNOPM = FurnaceInstrumentViewOPNOPM;
class FurnaceInstrumentViewOpOPNOPM {
constructor(offset, operator, vars) {
this.offset = offset;
this.operator = operator;
this.vars = vars;
}
get amplitudeModulation() { return this.vars.fmInsOpData[this.offset + 0]; }
set amplitudeModulation(value) { this.vars.fmInsData[this.offset + 0] = value; }
get attackRate() { return this.vars.fmInsOpData[this.offset + 1]; }
set attackRate(value) { this.vars.fmInsData[this.offset + 1] = value; }
get decay1Rate() { return this.vars.fmInsOpData[this.offset + 2]; }
set decay1Rate(value) { this.vars.fmInsData[this.offset + 2] = value; }
get multiple() { return this.vars.fmInsOpData[this.offset + 3]; }
set multiple(value) { this.vars.fmInsData[this.offset + 3] = value; }
get releaseRate() { return this.vars.fmInsOpData[this.offset + 4]; }
set releaseRate(value) { this.vars.fmInsData[this.offset + 4] = value; }
get decay1Level() { return this.vars.fmInsOpData[this.offset + 5]; }
set decay1Level(value) { this.vars.fmInsData[this.offset + 5] = value; }
get totalLevel() { return this.vars.fmInsOpData[this.offset + 6]; }
set totalLevel(value) { this.vars.fmInsData[this.offset + 6] = value; }
get rateScale() { return this.vars.fmInsOpData[this.offset + 8]; }
set rateScale(value) { this.vars.fmInsData[this.offset + 8] = value; }
get detune() { return this.vars.fmInsOpData[this.offset + 9]; }
set detune(value) { this.vars.fmInsData[this.offset + 9] = value; }
get decay2Rate() { return this.vars.fmInsOpData[this.offset + 10]; }
set decay2Rate(value) { this.vars.fmInsData[this.offset + 10] = value; }
get ssgeg() { return this.vars.fmInsOpData[this.offset + 11]; }
set ssgeg(value) { this.vars.fmInsData[this.offset + 11] = value; }
get amplitudeModulationMacro() {
return this.vars.amplitudeModulationMacro === null ? null : this.vars.amplitudeModulationMacro[this.operator];
}
get attackRateMaco() {
return this.vars.attackRateMaco === null ? null : this.vars.attackRateMaco[this.operator];
}
get decay1RateMacro() {
return this.vars.decay1RateMacro === null ? null : this.vars.decay1RateMacro[this.operator];
}
get multipleMacro() {
return this.vars.multipleMacro === null ? null : this.vars.multipleMacro[this.operator];
}
get releaseRateMacro() {
return this.vars.releaseRateMacro === null ? null : this.vars.releaseRateMacro[this.operator];
}
get decay2LevelMacro() {
return this.vars.decay2LevelMacro === null ? null : this.vars.decay2LevelMacro[this.operator];
}
get totalLevelMacro() {
return this.vars.totalLevelMacro === null ? null : this.vars.totalLevelMacro[this.operator];
}
get rateScaleMacro() {
return this.vars.rateScaleMacro === null ? null : this.vars.rateScaleMacro[this.operator];
}
get detuneMacro() {
return this.vars.detuneMacro === null ? null : this.vars.detuneMacro[this.operator];
}
get decay2RateMacro() {
return this.vars.decay2RateMacro === null ? null : this.vars.decay2RateMacro[this.operator];
}
get ssgegMacro() {
return this.vars.ssgegMacro === null ? null : this.vars.ssgegMacro[this.operator];
}
}
exports.FurnaceInstrumentViewOpOPNOPM = FurnaceInstrumentViewOpOPNOPM;
var FurnaceAmigaModeEnum;
(function (FurnaceAmigaModeEnum) {
FurnaceAmigaModeEnum[FurnaceAmigaModeEnum["sample"] = 0] = "sample";
FurnaceAmigaModeEnum[FurnaceAmigaModeEnum["wavetable"] = 1] = "wavetable";
})(FurnaceAmigaModeEnum = exports.FurnaceAmigaModeEnum || (exports.FurnaceAmigaModeEnum = {}));
class FurnaceInstrumentViewAmiga {
constructor(vars) {
this.vars = vars;
this.type = FurnaceInstrumentTypeEnum.Amiga;
}
get sampleId() { const sample = this.vars.amigaInsData[0]; return sample === 0xFFFF ? null : sample; }
set sampleId(value) { this.vars.amigaInsData[0] = value !== null && value !== void 0 ? value : 0xFFFF; }
get mode() { return this.vars.amigaInsData[2]; }
set mode(value) { this.vars.amigaInsData[2] = value; }
get waveLen() { return this.vars.amigaInsData[3]; }
set waveLen(value) { this.vars.amigaInsData[3] = value; }
get waveSize() { return this.vars.amigaInsData[16]; }
set waveSize(value) { this.vars.amigaInsData[16] = value; }
get volumeMacro() { return this.vars.volumeMacro; }
get arpeggioMacro() { return this.vars.arpeggioMacro; }
get pitchMacro() { return this.vars.pitchMacro; }
get phaseResetMacro() { return this.vars.phaseResetMacro; }
}
exports.FurnaceInstrumentViewAmiga = FurnaceInstrumentViewAmiga;