157 lines
3 KiB
JavaScript
157 lines
3 KiB
JavaScript
function parse (buffer) {
|
|
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 <= buffer.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 buffer.readInt8(i++)
|
|
}
|
|
|
|
function readShort () {
|
|
const short = buffer.readInt16LE(i)
|
|
i += 2
|
|
return short
|
|
}
|
|
|
|
function readInt () {
|
|
const int = buffer.readInt32LE(i)
|
|
i += 4
|
|
return int
|
|
}
|
|
|
|
function readString () {
|
|
let length = readInt()
|
|
let string = ''
|
|
for (; length > 0; length--) string += String.fromCharCode(readByte())
|
|
return string
|
|
}
|
|
}
|
|
|
|
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 }
|