Need help with NBS format binary parsing (erroring)

Started by pjals_but_noisy, Oct 22, 2021, 02:30 PM

Previous topic - Next topic

pjals_but_noisy

im making a nbs implementation for CC/Pure Lua and its erroring, why is this happening?
here is the library i used (bitbuffer), https://github.com/Dekkonot/bitbuffer

the output goes like:
> it4.nbs (test nbs)
< 5
< aaaa
< 256
< 0 256
<! opennbs.lua:72: attempt to index field '?' (a nil value)

and here is the code:
local bitbuffer = require("bitbuffer")
local pretty = require("cc.pretty")

local function readStr(buffer)
local size = buffer.readInt32()
return buffer.readSetLengthString(size)
end

local function parseNbs(path)
local handle = fs.open(path, "rb")
handle.read(2)
local buffer = bitbuffer(handle.readAll())
handle.close()
local info, layers = {}, {}
info.version = buffer.readByte()
info.layers = {}
info.author = {}
info.clicks = {}
info.noteblocks = {}
print(info.version)
if info.version == 5 then
-- Header / Metadata
info.vic = buffer.readByte()
info.length = buffer.readInt16()
info.layers = buffer.readInt16()
info.name = readStr(buffer)
info.author.nbs = readStr(buffer)
info.author.original = readStr(buffer)
info.desc = readStr(buffer)
info.tempo = buffer.readInt16() / 100 -- ticks*100 -> ticks
info.autoSave = buffer.readByte()
info.asInterval = buffer.readByte()
info.ts = buffer.readByte()
info.timeSpent = buffer.readInt32() * 60 -- minutes -> seconds
info.clicks.left = buffer.readInt32()
info.clicks.right = buffer.readInt32()
info.noteblocks.added = buffer.readInt32()
info.noteblocks.removed = buffer.readInt32()
info.realname = readStr(buffer)
info.loop = buffer.readByte()
info.loopCount = buffer.readByte()
info.loopStart = buffer.readInt16()
-- Notes
local tick = 0
while true do
local jumps = buffer.readInt16()
if jumps == 0 then
print("a")
break
end
tick = tick + jumps
local layer = 0
layers[layer] = {}
layers[layer].notes = {}
print("aaaa")
while true do
local lJumps = buffer.readInt16()
if lJumps == 0 then
print(lJumps)
break
end
print(lJumps)
print(layer, layer + lJumps)
layer = layer + lJumps

local instrument = buffer.readByte()
local key = buffer.readByte()
local velocity = buffer.readByte()
local panning = buffer.readByte()
local pitch = buffer.readInt16()

layers[layer].notes[tick] = {}
layers[layer].notes[tick].instrument = instrument
layers[layer].notes[tick].key = key
layers[layer].notes[tick].velocity = velocity
layers[layer].notes[tick].panning = panning
layers[layer].notes[tick].pitch = pitch
print(layer, "a")
end
end
--Layers
for i = 1, info.layers do
pretty.print(pretty.pretty(layers))
print(i)
layers[i].name = readStr(buffer)
layers[i].lock = buffer.readByte()
layers[i].volume = buffer.readByte()
layers[i].pan = buffer.readByte()
end

return { ["info"] = info, ["layers"] = layers }
else
error("NBS file is outdated. Required version: 5. (got " .. info.version .. ")")
end
end

pretty.print(pretty.pretty(parseNbs(read())))
a

Lupus590

#1
The error message is telling you that you are trying to use something as a table that is not a table. It could be that the table is not ready yet.

Looking at you code line 72 (the line number that the error is blaming) is this line

layers[layer].notes[tick] = {}
That's quite the nested table and any of those could be not actually a table.

I would check that the table exists before trying to use it, and if it doesn't then make it, you have to do this for each level of the nesting of the table.

if not layers then
  layers = {}
end
if not layers[layer] then
  layers[layer] = {}
end
if not layers[layer].notes then
  layers[layer].notes = {}
end

pjals_but_noisy

#2
Quote from: Lupus590 on Oct 22, 2021, 06:05 PMThe error message is telling you that you are trying to use something as a table that is not a table. It could be that the table is not ready yet.

Looking at you code line 72 (the line number that the error is blaming) is this line

layers[layer].notes[tick] = {}
That's quite the nested table and any of those could be not actually a table.

I would check that the table exists before trying to use it, and if it doesn't then make it, you have to do this for each level of the nesting of the table.

if not layers then
  layers = {}
end
if not layers[layer] then
  layers[layer] = {}
end
if not layers[layer].notes then
  layers[layer].notes = {}
end
im pretty sure thats half the problem, since its normally not supposed to return 256 for everything
(and great, now its reading past the bounds)
a

pjals_but_noisy

#3
oh look, i got it working, great.... nevermind, it thinks all notes are on layer 256? man binary is confusing
a