-- simple_nbs_player.lua
-- Minimal NBS player for CraftOS 1.7 + OpenPeripheral note blocks
local nb = peripheral.wrap("right") -- change side to your note block
if not nb then
print("No note block peripheral found!")
return
end
-- Load .nbs file (binary)
local function loadNBS(filename)
local f = fs.open(filename, "rb")
if not f then return nil end
local data = f.readAll()
f.close()
return data
end
-- Convert bytes to little-endian 16-bit integer
local function readShort(data, pos)
local a = string.byte(data, pos)
local b = string.byte(data, pos+1)
return a + b*256
end
-- Simple parsing for minimal NBS (version 3–5)
local function parseNBS(data)
local pos = 8 -- skip header (short length + version info)
local tempo = readShort(data, pos) / 100 -- ticks per beat
pos = pos + 2
local notes = {} -- {tick = {{layer, instrument, key}, ...}}
local tick = 0
while pos < #data do
local jumpTicks = readShort(data, pos)
pos = pos + 2
if jumpTicks == 0 then break end
tick = tick + jumpTicks
local layer = 0
while true do
local jumpLayers = readShort(data, pos)
pos = pos + 2
if jumpLayers == 0 then break end
layer = layer + jumpLayers
local instrument = string.byte(data, pos)
local key = string.byte(data, pos+1)
pos = pos + 2
if not notes[tick] then notes[tick] = {} end
table.insert(notes[tick], {layer=layer, instrument=instrument, key=key})
end
end
return notes, tempo
end
-- Map NBS instruments to Minecraft sounds
local instrumentMap = {
[0] = "note.harp",
[1] = "note.bass",
[2] = "note.snare",
[3] = "note.hat",
[4] = "note.bassattack"
}
-- Convert NBS key to pitch (rough approximation)
local function keyToPitch(key)
return 2 ^ ((key - 45) / 12)
end
-- Play parsed notes
local function playNBS(notes, tempo)
local sortedTicks = {}
for tick in pairs(notes) do table.insert(sortedTicks, tick) end
table.sort(sortedTicks)
for _, tick in ipairs(sortedTicks) do
local tickNotes = notes[tick]
for _, n in ipairs(tickNotes) do
local sound = instrumentMap[n.instrument] or "note.harp"
local pitch = keyToPitch(n.key)
nb.playSound(sound, 1, pitch)
end
sleep(tempo) -- wait until next tick
end
end
-- ===== Main =====
local filename = "song.nbs"
local data = loadNBS(filename)
if not data then
print("Failed to load "..filename)
return
end
local notes, tempo = parseNBS(data)
print("Playing "..filename.." at tempo "..tempo)
playNBS(notes, tempo)
print("Done!")