Home › Forums › General › Programming › tonumber to convert to hex?
Tagged: tonumber; convert to hex;
- This topic has 21 replies, 4 voices, and was last updated 6 years, 8 months ago by goodweather.
-
AuthorPosts
-
August 4, 2017 at 6:16 pm #72611
hi,
i want to convert ascii to hex. i can currently do it to decimal
(using something i found) and there’s an example panel to illustrate
here:https://app.box.com/s/ftfr2jniuv0diaaxbapfxvqm24xkp0yw
(getDatas v02.panel)
i see in Goodweather’s DSI Pro2 panel ‘miscellaneous’ method:
-- For the conversion of a DECimal number to anything else -- it is just needed to use the built-in Lua function tonumber(string, base) -- -- print(tonumber("0100",2)) -- 4 -- print(tonumber("3F",16)) -- 63
and i would like to figure out how to use it in a method.
i tried a couple of things but it was just poking around
in the dark. one worked, the other reported a concatenation
with a global variable error. i’ve forgotten what i did this
morning, it may not have been far off.
does tonumber() ‘know’ the characters for hex representation?
must assume it does, if it can convert 3F to 63.i tried to mess around with this:
panel:getComponent("label_character1"):setPropertyString("uiLabelText",""..(character1))
and put instead:
setPropertyString("uiLabelText",""..(tonumber(character1),16)
i think that one produced the concatenation error …
the other one actually produced a result, but it was a 3-figure
decimal, not what i was after.August 6, 2017 at 4:31 am #72622Hopefully this helps.
This is the method I use in a panel I’m developing for the Kurzweil PC3/Artis/Forte
Symbols is an array initialized in my initializePanel method. (Borrowed from the Miniak Panel, as the PC3 uses the same symbol set)
symbols = { [0]=””,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,
“|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,
” “,”!”,”\””,”#”,”$”,”%”,”&”,”‘”,”(“,”)”,”*”,”+”,”,”,”-“,”.”,”/”,
“0”,”1″,”2″,”3″,”4″,”5″,”6″,”7″,”8″,”9″,”:”,”;”,”<","=",">“,”?”,
“@”,”A”,”B”,”C”,”D”,”E”,”F”,”G”,”H”,”I”,”J”,”K”,”L”,”M”,”N”,”O”,
“P”,”Q”,”R”,”S”,”T”,”U”,”V”,”W”,”X”,”Y”,”Z”,”[“,”\\”,”]”,”^”,”_”,
“`
“,”a”,”b”,”c”,”d”,”e”,”f”,”g”,”h”,”i”,”j”,”k”,”l”,”m”,”n”,”o”,
“p”,”q”,”r”,”s”,”t”,”u”,”v”,”w”,”x”,”y”,”z”,”{“,”|”,”}”,”~”,”|”}
symbols2 = { [0]=””,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,
“|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,
” “,”!”,”\””,”#”,”$”,”%”,”&”,”\'”,”(“,”)”,”*”,”+”,”,”,”-“,”.”,”/”,
“0”,”1″,”2″,”3″,”4″,”5″,”6″,”7″,”8″,”9″,”:”,”;”,”<","=",">“,”?”,
“@”,”A”,”B”,”C”,”D”,”E”,”F”,”G”,”H”,”I”,”J”,”K”,”L”,”M”,”N”,”O”,
“P”,”Q”,”R”,”S”,”T”,”U”,”V”,”W”,”X”,”Y”,”Z”,”[“,”\\”,”]”,”^”,”_”,
“`”,”a”,”b”,”c”,”d”,”e”,”f”,”g”,”h”,”i”,”j”,”k”,”l”,”m”,”n”,”o”,
“p”,”q”,”r”,”s”,”t”,”u”,”v”,”w”,”x”,”y”,”z”,”{“,”|”,”}”,”~”,”|”}Data is the SYSEX dump assigned in the MIDI Receive method
data = midi:getData()
To generate the Program name I do this
local a={} for i=0,30 do -- this collects first 31 bytes and puts them into array a. This should include the program name. a=data:getByte(i) end –for
Then later.
j=11 while a[j] ~= 0x00 do name = name..symbols[a[j]] j=j+1 end --while prgName[receivedProgramNum]=": "..name -- update Program Received currentProg = string.format(nPrg) panel:getComponent("recProg"):setComponentText(currentProg)
I need the while statement because on the PC3 the program name is variable length and delimited by 0x00. If you have a fixed length program name you could make the while statement while a[j] < 20 (for example)
- This reply was modified 6 years, 8 months ago by Puppeteer.
- This reply was modified 6 years, 8 months ago by Puppeteer.
The Puppeteer
http://godlike.com.auAugust 6, 2017 at 6:10 am #72625haha well thanks for the symbols list 🙂 i can copy that.
was dreading having to type that lot out in notepad… i think
i’ve got a wrong count for ascii to decimal anyway: i think
‘A’ should be 47 not 48 (??? …forgotten… or is that ‘0’..)
-we need a ‘resources’ sticky somewhere with useful stuff
like that.it would be useful to see what tonumber() (class?) looks like,
eg: what is does/how it works.all i’m trying to do at this point is send the separate byte results
to their labels, the way i’m doing with the decimal. i can see how
tonumber() works with ‘print’/console (in theory) but didn’t yet
get it to write to a label withsetProperty("uiLabelText")
nb: my ‘coding’ is still extremely basic: i can manage routine stuff
quite well now, find a few things for myself, but not much good with
iterative/recursive stuff yet.i *really really* need some way to play around with console-type
results within the Ctrlr workspace – can’t be too hard to send it
to a uiLabel rather than Console?(my imagination is a bit lumpen
as i write; need to pick up on that idea again).because this, to me, is how i’m going to master assigning variables,
iteration operations etc. – ie: a friendlier way of observing results,
because i find opening the console page before triggering the method
not very satisfying – note that i quite like making these little
demo panels to test something out while i get the hang of it.(can kick
up all sorts of ideas/revelations too)August 6, 2017 at 11:03 am #72627The last line of my example does this
‘
panel:getComponent(“recProg”):setComponentText(currentProg)
‘The Puppeteer
http://godlike.com.auAugust 6, 2017 at 11:00 pm #72628Here is how I convert ASCII to HEX. You could do it using loops but with as few as 18 chars I went the stupid way:
-- GET the Patch Name local PatchName=L(panel:getComponent("PatchName"):getPropertyString("uiLabelText")) local PatchNameUp=string.upper(PatchName) -- Store each char in a variable and convert it from ASCII to numerical code local char1 =string.byte(PatchNameUp, 1) local char2 =string.byte(PatchNameUp, 2) local char3 =string.byte(PatchNameUp, 3) local char4 =string.byte(PatchNameUp, 4) local char5 =string.byte(PatchNameUp, 5) local char6 =string.byte(PatchNameUp, 6) local char7 =string.byte(PatchNameUp, 7) local char8 =string.byte(PatchNameUp, 8) local char9 =string.byte(PatchNameUp, 9) local char10=string.byte(PatchNameUp,10) local char11=string.byte(PatchNameUp,11) local char12=string.byte(PatchNameUp,12) local char13=string.byte(PatchNameUp,13) local char14=string.byte(PatchNameUp,14) local char15=string.byte(PatchNameUp,15) local char16=string.byte(PatchNameUp,16) local char17=string.byte(PatchNameUp,17) local char18=string.byte(PatchNameUp,18) -- Check for empty chars and put each char value in _G["ToneTabNr"..t] (with corresponding byte number) if char1 == nil then char1 =32 end _G[PatchTblName..p][10]=string.format("%.2x", char1) if char2 == nil then char2 =32 end _G[PatchTblName..p][11]=string.format("%.2x", char2) if char3 == nil then char3 =32 end _G[PatchTblName..p][12]=string.format("%.2x", char3) if char4 == nil then char4 =32 end _G[PatchTblName..p][13]=string.format("%.2x", char4) if char5 == nil then char5 =32 end _G[PatchTblName..p][14]=string.format("%.2x", char5) if char6 == nil then char6 =32 end _G[PatchTblName..p][15]=string.format("%.2x", char6) if char7 == nil then char7 =32 end _G[PatchTblName..p][16]=string.format("%.2x", char7) _G[PatchTblName..p][17]="00" -- This Byte is not used if char8 == nil then char8 =32 end _G[PatchTblName..p][18]=string.format("%.2x", char8) if char9 == nil then char9 =32 end _G[PatchTblName..p][19]=string.format("%.2x", char9) if char10== nil then char10=32 end _G[PatchTblName..p][20]=string.format("%.2x",char10) if char11== nil then char11=32 end _G[PatchTblName..p][21]=string.format("%.2x",char11) if char12== nil then char12=32 end _G[PatchTblName..p][22]=string.format("%.2x",char12) if char13== nil then char13=32 end _G[PatchTblName..p][23]=string.format("%.2x",char13) if char14== nil then char14=32 end _G[PatchTblName..p][24]=string.format("%.2x",char14) _G[PatchTblName..p][25]="00" -- This Byte is not used if char15== nil then char15=32 end _G[PatchTblName..p][26]=string.format("%.2x",char15) if char16== nil then char16=32 end _G[PatchTblName..p][27]=string.format("%.2x",char16) if char17== nil then char17=32 end _G[PatchTblName..p][28]=string.format("%.2x",char17) if char18== nil then char18=32 end _G[PatchTblName..p][29]=string.format("%.2x",char18)
August 7, 2017 at 9:31 am #72629Puppeteer’s method is a bit complex for what i need.
i recognise Possemo’s because it is similar to what
i’ve used so far to extract from ascii characters on the
label to separate labels, as decimal numbers
-but i realise i have no idea how it works 🙂? > what is ‘string.byte’, as in:
character1 = string.byte(NewPatchName,1)
i assumed it just goes through a string assigning each
character as a byte..but how does it know what decimal
to assign to characters?Possemo please explain your method, it
looks like it could do it here – if you could go through
and explain what’s going on … you know how useless
i am at coding lol so …here’s what i found in Goodweather’s panel:
dec2hex = function(num) local hexstr = '0123456789ABCDEF' local s = '' while num > 0 do local mod = math.fmod(num, 16) s = string.sub(hexstr, mod+1, mod+1) .. s num = math.floor(num / 16) end if s == '' then s = '0' end return s end
and:
function str2hex(str) local hex = '' while #str > 0 do local hb = dec2hex(string.byte(str, 1, 1)) if #hb < 2 then hb = '0' .. hb end hex = hex .. hb str = string.sub(str, 2) end return hex end
how/where would one use these?(and how do they work?)
i’m going to try out your code and see what happens,
in the meantime.August 8, 2017 at 7:30 am #72631(Puppeteer: i think i can see what your method does – it isn’t quite
what i’m trying to do, as it produces a single string/result)OK i tried Possemo’s and got a string concatenation error
-global PatchTblName was a nil value, because i haven’t got it defined.so it is trying to concatenate it into a single string – i’m not ready
for that yet 🙂 i am trying to send each ‘byte’ individually to its own
label first – just to check/observe conversion to hex.
that’s why i’m curious about tonumber(string,base) – and these other
convert methods.my current ‘enterToneName’, at this point, goes:
if value~=nil then panel:getComponent("label_character1"):setPropertyString("uiLabelText",""..(character1)) panel:getComponent("label_character2"):setPropertyString("uiLabelText",""..(character2)) panel:getComponent("label_character3"):setPropertyString("uiLabelText",""..(character3)) panel:getComponent("label_character4"):setPropertyString("uiLabelText",""..(character4)) panel:getComponent("label_character5"):setPropertyString("uiLabelText",""..(character5)) panel:getComponent("label_character6"):setPropertyString("uiLabelText",""..(character6)) panel:getComponent("label_character7"):setPropertyString("uiLabelText",""..(character7)) panel:getComponent("label_character8"):setPropertyString("uiLabelText",""..(character8)) panel:getComponent("label_character9"):setPropertyString("uiLabelText",""..(character9)) panel:getComponent("label_character10"):setPropertyString("uiLabelText",""..(character10)) end
and this sends the text characters onto the labels as decimals – but not
as hex. i’m thinking i need a little subfunction i can invoke at this
point to perform translation on each byte (ok, i know it won’t be any
use at this stage, because hex needs the prefix ‘0x’ to be useful – unless
i include that in the process).August 8, 2017 at 8:26 am #72632ok: myBad: … i’m not conversant with ‘%.2x’. or was lost
in the avalanche of things i’ve been familiarising myself
with.reading this: (if you can think of more targeted info…)
https://www.quora.com/What-does-2x-do-in-C-codeso it appears ‘%’ means hex?
and this is a representation/definition of string format?
(still looking for more reading matter..)”
On the difference of the meaning of 2 in “0x%2x” and “0x%.2x”:In “0x%2x” the 2 defines the “fieldwidth”: if the hex representation of the value consists of less than 2 digits, it is prefixed with spaces to end up with a fieldwidth of 2.
In “0x%.2x” the 2 defines the precision: there will be at least 2 hex digits in the result, if the representation of the value has less digits, it is prefixed with 0’s
Some examples (using 4 as width, for clarity):
Printf(“0x%4x”,12) “0x C”
Printf(“0x%.2x”,12) “0x0C”
Printf(“0x%4.2x”,12) “0x 0C”
Printf(“0x%04x”,12) “0x000C”
”mmm.. so i can generate the ‘0x’ prefix like that, yeah?
August 8, 2017 at 9:49 pm #72633Hi,
once again, I think you are searching too far and too complex…
What do you want to achieve precisely?
Do you need the hexa representation or the values?
An hexa value is the same as the corresponding decimal one
So, writing myVar = 0x2A is the same as writing myVar = 42
You write 0x to indicate it is hexa.
Please note that there are no quotes around 0x2A because it is not a string but a value.tonumber() is a standard Lua function as tostring().
tonumber converts from any base to decimal.So, back to basics: what do you want to achieve?
From there I can hopefully guide you in an easy way 🙂August 8, 2017 at 10:41 pm #72642Something else…
In your initial post you get an error with
setPropertyString("uiLabelText",""..(tonumber(character1),16)
It’s because you made errors the end.
.. concatenates strings. So you must have strings…
with tonumber() you get… a number 😉
Correct syntax is thus:
setPropertyString("uiLabelText", tostring(tonumber(character1, 16)))
Assuming character1 is a string looking as an hexa number.
character1 = “2A”August 9, 2017 at 5:21 am #72643aha. thanks – i tried it but it isn’t producing expected results 🙂
here, have a look at this little test panel:
one method extracts decimal numbers from the text string,
and the other is supposed to extract it as hex.(look in the ‘reference’ lua folder)
https://app.box.com/s/g0gtzm1oiwcxf76875143lbq6vliapzt
(getDatas_v08.panel)
edit: looks like it is treating the source number as a
hexadecimal it wants to convert to decimal: 50 is decimal
for 0x32 – so tonumber would appear to convert TO decimal,
but not to hex.(correct?)what are dec2hex and strng2hex for, and how are they used?
Possemo’s method with the %.2x seems like the path to
pursue.. but it’s missing a line about that global macro
thingy.(is it?)August 9, 2017 at 1:56 pm #72644Looking at your panel…
Can you explain me what you are trying to do (not what you do in this conversion)?
Like: a get a patch in sysex and wants to convert to decimal OR I have a text file containing hexa text separated by blanks and wants to see it in decimal OR…Knowing that I can surely help you.
Coming back to your panel (please correct me)
– you enter a patch name
– pressing enterToneName you get the decimal representation
– pressing getHex you want to get the same but in hexatonumber(string, base): standard Lua function converting a number represented as a string in a certain base to decimal
Example1: from binary to decimal you do tonumber(“0101”, 2) to give 5
Example2: from hexa to decimal you do tonumber(“3F”, 16) to give 63dec2hex(integer): “decimal to hexa” = own function to convert an integer to an hexa represented as a string (thus not the hexa value!)
dec2hex(63) gives “3F”
In Ctrlr console you test with
console(tostring(dec2hex(63)))
In your code if you write 63 or 0x3F (without any quote), this is exactly the same. You are using the value of the number; not its representation.
This is very important to understand! Don’t mix value and text representation.
You should use text representation only to show to the user (seldom needed) or to verify some value when not in decimal.str2hex(string): “string to hexa” = own function to convert a string to an hexa representation as a string
str2hex(“Hello”) gives “48656C6C6F”
In Ctrlr console you test with
console(tostring(str2hex("Hello")))
I’m using this function to store patch names in sysex.For all sysex and patch manipulations (reading, writing, modifying) I strongly advise you to use MemoryBlocks. Very easy to use and very flexible. You can read any byte or range, append, suppress, replace… perform operations between blocks…
for your getHex and to get your 8 LCD filled in:
– fill lcd1 with string.sub(str2hex(patchname),1,2)
– fill lcd2 with string.sub(str2hex(patchname),3,4)
…Back to the main question: why do you want to see the hexa string of the name?
August 9, 2017 at 10:14 pm #72646I’m a bit late, here is a little explanation of my code. I have to say that this is Carl Licroy’s code not mine. I copied it from one of his panels. This is a snippet of a method that copies the actual patch data (including the patch name from an uiLabel) into the library. It will construct a valid sysex dump that can be sent to the synth or saved to disk.
string.byte(PatchNameUp, 1)
This returns the numerical code of the first character of the string called PatchNameUp. So for “ALCOHOL” it would return 65 – the numerical code of “A”.Then I put the number into a table to construct the sysex dump:
PatchDataValuesTable[10]=string.format("%.2x", char1)
string.format formats a string. I know this is a bit strange. Maybe Goodweather would know a more elegant way but it works. %x will convert the number it to hex, .2 will always return two digits, like 04, or 0F – needed for a working sysex dump.Btw. string.format is very useful when you want to ouput a numeric variable to the console for debugging / checking purpose.
MyNumber=45 console(MyNumber) -- this does not work - console needs a string. -- you can do it like this: console(string.format("%x", MyNumber)) -- as hex console(string.format("%d", MyNumber)) -- as decimal console(string.format("%c", MyNumber)) -- as ascii charcter
There are lots of other string.format variations, see here:
https://www.gammon.com.au/scripts/doc.php?lua=string.formatIt may be a bit weird making a table filled with strings when you want a hex sysexdump but it works flawlessly and the code is very fast. When you want to send the sysex dump to the synth you just have to do this:
-- the table has 279 records. concatenate them all into a single string with a space between the records. PatchDat=table.concat(PatchDataValuesTable," ",1,279) -- make a memoryblock out of the big string MemB=MemoryBlock(PatchDat) -- send it to the synth panel:sendMidiMessageNow(CtrlrMidiMessage(MemB))
August 10, 2017 at 1:37 pm #72648Well, even if this method is working I would say it doesn’t sound so straightforward / efficient imho…
You would work directly with MemoryBlocks where each byte is a value that you can adapt as you want without getting the burden of string manipulations.
A sysex dump is a memory block; a file content can go to a memory block; the midi message data is memory block…Some examples:
-- empty mb creation BasicProgramData = MemoryBlock() -- creation based on another mb LoadedProgramData = MemoryBlock(BasicProgramData) -- checking size (used for dumps) LoadedProgramData:getSize() == 1024 -- converting patch name into a mb using my function str2hex explained above mbTemp = MemoryBlock(str2hex(txtProgramName:getComponent():getProperty("uiLabelText"))) -- replacing a 20 characters patch name in an existing mb LoadedProgramData:copyFrom (mbTemp,378, 20) -- setting a byte according to a modulator value. 4 is the offset in the sysex dump LoadedProgramData:setByte(4, modOsc1Pitch:getModulatorValue()) -- setting a modulator based on a byte modOsc1Pitch:setValue(LoadedProgramData:getByte(4), true) -- setting a label based on a range of bytes txtProgramName:getComponent():setPropertyString ("uiLabelText", LoadedProgramData:getRange(378,20):toString())
Actually in a panel, beside a patch name, all data is numbers. So why going to hexa text and not using hexa directly? And a patch name can easily get converted to numbers.
So you can just do things like the following, there are the same:LoadedProgramData:setByte(4, modOsc1Pitch:getModulatorValue()) LoadedProgramData:setByte(4, 63) LoadedProgramData:setByte(4, 0x3F)
On top of that, in many cases, the bytes get packed/unpacked.
So I would say:
– make a memory block (empty or not, copied from another one…)
– adapt content with setByte, append, copyFrom…
– send as midi message or save to a fileInfo on memory blocks at Juce API: https://www.juce.com/doc/classMemoryBlock
There will be a paragraphs on mb in Step by step guide 2.0 (I have fixed a release date target to end of this year – whatever state. It is delayed because I’m changing from Sub37 explanations to Pro 2 ones + adding a lot of stuff. Also delayed because I’m doing further additions to my Pro 2 panel + created a Prophet 12 one)
Good discussion even if the initial topic was looking very simple to answer 🙂
August 10, 2017 at 8:02 pm #72649great, more stuff to try 🙂
in fact i found a solution after my last post, and can now
concatenate a table with spaces(or whatever you want) between
bytes hehe. new mini-panel here:
https://app.box.com/s/5iwzgwcnrkmkcrjmn6serq0d64e1u3rii did this:
hexNameTabl={} --etc if character1 == nil then character1 = "32" else character1 = ""..character1 end hexNameTabl[1] = string.format("%.2x", character1) --etc. panel:getComponent("label_character11"):setPropertyString("uiLabelText",hexNameTabl[1]) --etc
setPropertyString needed the table part with square brackets but would not
accept it with regular brackets and comma – is that because it was a macro
before ( with the Carl Licroy method)?this gets individual bytes onto the labels. and then to put them all in
a single string with spaces beteen on a single label:hexDatasConcat = table.concat(hexNameTabl, "-", 1, 10) --console ("hexDatasConcat : "..hexDatasConcat) panel:getComponent("label_hex"):setPropertyString("uiLabelText",""..hexDatasConcat))
edit: correction: i put a ‘-‘ (hyphen) instead of a space with that example, just to check what happened/where they were inserted.
August 10, 2017 at 8:58 pm #72651Well, as I explained above, I just find the method not adequate at all.
But this is the beauty of programming: a lot of different ways to achieve some result…
Just a matter of taste and colors 😉August 10, 2017 at 10:23 pm #72652@goodweather: I remember when I quickly looked into your panel I saw that you manipulate memoryblocks directly. Unfortuntely, at that time I already finished my panels. When you are not experienced in coding it is maybe a bit easier to work with strings first. You can debug it easily. Well this could be just false pretence. On my next panel I will try your way.
@human fly: one unconvenient thing about working with tables and converting them later into memoryblocks: Lua tables are starting with record [1], memoryblocks are starting with byte 0. When you want to put a value into byte position 10 you must put it into table record nr [11]. So a dump begins with PatchDataValuesTable[1]=”F0″ (will be byte nr. 0)
August 10, 2017 at 10:33 pm #72653Héhé… and I don’t remember how I discovered the memory blocks… Hahaha, funny…
Either the Virus panel from dasfaker or some other forum topic.Anyway, when I find a new object, mainly by reading Ctrlr forum topics, I’m then looking in Juce API to check if this is not an object and if yes I can then see all the possible functions (did it for mb but also for checking the left/right keys…
About memory blocks, they are very flexible…
August 11, 2017 at 2:53 pm #72655Well, as I explained above, I just find the method not adequate at all.
But this is the beauty of programming: a lot of different ways to achieve some result…
Just a matter of taste and colors ?haha well i’m a newb so i’m trying to get things working by any means
necessary, and i’ll worry about elegance later – i did see memory blocks
used, and did see that type of method, and it all looks interesting.
i just found this more accessible at this point – and i’m still juggling
lots of concepts i’m not fully conversant with.as for converting to text first: yes, agree, not necessary at all, just
wanted to get it visible on screen and play around with it a bit.
(if you want to have a look at where i’ve got to with my main panel,
i posted a recent instance on the D-110 thread)August 13, 2017 at 9:36 pm #72670…and I forgot to mention that if you want to see the content of a memory block in hexa (for verification in the console for example) then you do that with one single command. Easy 🙂
console(LoadedProgramData:toHexString(1))
-
AuthorPosts
- The forum ‘Programming’ is closed to new topics and replies.