aboutsummaryrefslogtreecommitdiff
path: root/lib/osc.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lib/osc.lua')
-rw-r--r--lib/osc.lua76
1 files changed, 76 insertions, 0 deletions
diff --git a/lib/osc.lua b/lib/osc.lua
new file mode 100644
index 0000000..66f378a
--- /dev/null
+++ b/lib/osc.lua
@@ -0,0 +1,76 @@
+--
+-- 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 <https://www.gnu.org/licenses/>.
+--
+
+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