UNPKG

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
"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;