// const fs = require('fs') // const path = require('path') // const instrumentNames = require('./instrument-names.json') function parse (buf) { // const buf = fs.readFileSync(filepath) let i = 0 let songLength = 0 let format = 0 let vanillaInstrumentCount = 0 songLength = readShort() if (songLength === 0) { format = readByte() } if (format >= 1) { vanillaInstrumentCount = readByte() } if (format >= 3) { songLength = readShort() } const layerCount = readShort() const songName = readString() const songAuthor = readString() const songOriginalAuthor = readString() const songDescription = readString() const tempo = readShort() const autoSaving = readByte() const autoSavingDuration = readByte() const timeSignature = readByte() const minutesSpent = readInt() const leftClicks = readInt() const rightClicks = readInt() const blocksAdded = readInt() const blocksRemoved = readInt() const origFileName = readString() let loop = 0 let maxLoopCount = 0 let loopStartTick = 0 if (format >= 4) { loop = readByte() maxLoopCount = readByte() loopStartTick = readShort() } const nbsNotes = [] let tick = -1 while (true) { const tickJumps = readShort() if (tickJumps === 0) break tick += tickJumps let layer = -1 while (true) { const layerJumps = readShort() if (layerJumps === 0) break layer += layerJumps const note = NBSNote() note.tick = tick note.layer = layer note.instrument = readByte() note.key = readByte() if (format >= 4) { note.velocity = readByte() note.panning = readByte() note.pitch = readShort() } nbsNotes.push(note) } } const nbsLayers = [] if (i <= buf.length) { for (let j = 0; j < layerCount; j++) { const layer = NBSLayer() layer.name = readString() if (format >= 4) { layer.lock = readByte() } layer.volume = readByte() if (format >= 2) { layer.stereo = readByte() } nbsLayers.push(layer) } } return { songLength, format, vanillaInstrumentCount, layerCount, songName, songAuthor, songOriginalAuthor, songDescription, tempo, autoSaving, autoSavingDuration, timeSignature, minutesSpent, leftClicks, rightClicks, blocksAdded, blocksRemoved, origFileName, loop, maxLoopCount, loopStartTick, nbsNotes, nbsLayers } function readByte () { return buf.readInt8(i++) } function readShort () { const byte1 = buf.readUint8(i++) const byte2 = buf.readUint8(i++) return (byte1 + (byte2 << 8)) } function readInt () { const byte1 = buf.readUint8(i++) const byte2 = buf.readUint8(i++) const byte3 = buf.readUint8(i++) const byte4 = buf.readUint8(i++) return (byte1 + (byte2 << 8) + (byte3 << 16) + (byte4 << 24)) } function readString () { let length = readInt() let str = '' for (; length > 0; --length) { let c = String.fromCharCode(readByte()) if (c === String.fromCharCode(0x0D)) { c = ' ' } str += c } return str } } function NBSNote () { return { tick: null, layer: null, instrument: null, key: null, velocity: 100, panning: 100, pitch: 0 } } function NBSLayer () { return { name: null, lock: 0, volume: null, stereo: 100 } } module.exports = { parse, NBSNote, NBSLayer }