How do I decode a string of 8 bit bytes

Okay so I did this but I’m getting an error

local RunService = game:GetService("RunService")
local HttpService = game:GetService("HttpService")

local byteString = HttpService:GetAsync('')

local char = string.char
local insert = table.insert

function byte_to_float(bin)
    local sig = bin:byte(2) % 0x80 * 0x10000 + bin:byte(3) * 0x100 + bin:byte(4)
    local exp = bin:byte(1) % 0x80 * 2 + math.floor(bin:byte(2) / 0x80) - 0x7F
        if exp == 0x7F then return 0 end
    return math.ldexp(math.ldexp(sig, -23) + 1, exp) * (bin:byte(1) < 0x80 and 1 or -1)
end

local function decode(hex)
    local str = hex:gsub("\\x%x%x", function(digits) return char(tonumber(digits, 16)) end)
    local floats = {}
    
    for i=1,str:len(),4 do
        insert(floats, byte_to_float(str:sub(i, i + 3)))
    end
    
    return floats
end

print(decode(byteString)[1])

output:

 invalid argument #1 to 'char' (number expected, got nil) <-- local str = hex:gsub("\\x%x%x", function(digits) return char(tonumber(digits, 16)) end)

local str = hex:gsub("\\x%x%x", function(digits) return char(tonumber(digits, 16)) end)
Should be
local str = hex:gsub("\\x%x%x", function(digits) return char(tonumber(digits:sub(3), 16)) end)
Which should remove the hex indicator from the start of each match.

Also, it sounds like your best bet would be sending the raw byte data to a file online, then requesting it in Roblox, instead of doing any hexadecimal conversions, as that introduces overhead and unnecessary storage usage.

1 Like

That fixed that part, but there was also an issue of the first line in your byte to float function

attempt to perform arithmetic (add) on number and

image

In regards to the first line, I believe it’d be better to write to the file using the wb (write binary) tag instead of the w (write text) one as you are working with byte data. This’d allow you to skip over the converting process later on.

(Sixteenth line would become: with open('scripts/wav/wav_bytes.txt', 'wb') as f:)

Actually that is a good point, but how would i get the normalized values from here in roblox?
image
Not talking about the question marks I believe that is a rendering issue but with the other characters

Simply use the string.byte function,

local str = "some string data here"
local bytes = {str:byte(1, -1)}

print(table.concat(bytes, "\n"))

Nevermind about the questionmarks, they actually do appear as they are
image

Oh this works. I will mark this as the solution. Thank you very much for the effort.

stack overflow (string slice too long)
here I would just split the string up then right?

Yea, probably into chunks of 1024 would be a reasonable size.

1 Like

How would I do that in roblox considering the entire thing is just full of random characters

local rep = string.rep
local insert = table.insert

local function split(str, csize)
	local out = {}
	local pattern = "."..rep(".?", csize - 1)
	
	for m in str:gmatch(pattern) do
		insert(out, m)
	end
	
	return out
end

Where str is the input string, and csize is the size of the chunks (1024 for the example number), and it outputs a table of strings with that length.

1 Like

What happens if #bytes % 1024 is not equal to zero? What happens to the remaining bytes?

They just get added as a string at the end, even if it isn’t the full length.

1 Like

Oh also here it says the pattern is too complex

local pattern = "."..string.rep(".?", csize - 1)

for m in str:gmatch(pattern) do
		table.insert(out, m)
	end

Sorry about that, I have written a different formula that might work better:

local insert = table.insert

local function split(str, csize)
	local out = {}
	
	for i=1,str:len(),csize do
	insert(out, str:sub(i, i + csize - 1))
	end
	
	return out
end

print(table.concat(split("test", 3), "\n"))
1 Like

Oh no need to apologize mate, sorry just want more thing.

So now that the bytes are split up, I tried to convert each byte into its value and then normalize it but it will return me only zero

local function split(str, csize)
	local out = {}
	
	for i=1,str:len(),csize do
        local value = str:sub(i, i + csize - 1):byte(1,-1)
        local normalized = (value - 128) / 127.0

	    table.insert(out, normalized)
	end
	
	return out
end

local chunks = split(byteString, 1024)

print(chunks[10])

which is weird because if I did this, it will spit out all the numbers correctly (128,128,128,…)

local function split(str, csize)
	local out = {}
	
	for i=1,str:len(),csize do
	    table.insert(out, str:sub(i, i + csize - 1))
	end
	
	return out
end

local chunks = split(byteString, 1024)

print(chunks[10]:byte(1,-1))

Hopefully this function should cover all your needs:

local insert = table.insert

local function split_and_normalise(str)
	local out = {}
	local csize = 1024
	
	for i=1,str:len(),csize do
		local res = {str:sub(i, i + csize - 1):byte(1, -1)}
		for i=1,#res do
			insert(out, (res[i] - 128) / 127.0)
		end
	end
	
	return out
end

print(table.concat(split_and_normalise("test"), "\n"))
1 Like

Yeah, it still returns zero. Just wondering are you returning an entire string for each chunk?

local function split_and_normalise(str)
	local out = {}
	local csize = 1024
	
	for i=1,str:len(),csize do
		local res = {str:sub(i, i + csize - 1):byte(1, -1)}
		for i=1,#res do
			table.insert(out, (res[i] - 128) / 127.0)
		end
	end
	
	return out
end

local chunks = split_and_normalise(byteString, 1024)

print(chunks[10])

what am i looking at … roblox went from obbys to this?

1 Like

To use it, just enter the string, no need for chunk size this time, and it returns a table of all the normalised values, so no need to index the table.