-- -- melisma - extensible and scriptable audio engine -- Copyright (C) 2026 Ludvig Gunne Lindström -- -- This program is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . -- local M = {} function M.decode(data) local addr,ttag,offset = string.unpack('!4 z Xs4 z Xs4',data) if offset == nil then error('invalid osc message') end ttag = string.sub(ttag,2) data = string.sub(data,offset) local args = {} for i = 1,#ttag do local format local c = string.sub(ttag,i,i) if c == 's' then format = '!4 z Xs4' elseif c == 'i' then format = '>i4' elseif c == 'f' then format = '>f' else error('invalid osc message') end local arg,offset = string.unpack(format,data) if offset == nil then error('invalid osc message') end table.insert(args,arg) data = string.sub(data,offset) end return {addr=addr, args=args} end function M.encode(msg) local addr = msg.addr local args = msg.args local data = '' local ttag = ',' for _,arg in pairs(args) do if type(arg) == 'string' then ttag = ttag..'s' data = data..string.pack('!4 z Xs4',arg) elseif type(arg) == 'number' then if math.type(arg) == 'integer' then ttag = ttag..'i' data = data..string.pack('>i4',arg) elseif math.type(arg) == 'float' then ttag = ttag..'f' data = data..string.pack('>f',arg) else error('unsupported argument type '..math.type(arg)) end else error('unsupported argument type '..type(arg)) end end return string.pack('!4 z Xs4',addr)..string.pack('!4 z Xs4',ttag)..data end return M