Help getting ASCII Characters into uiLabel

Home Forums General Programming Help getting ASCII Characters into uiLabel

Viewing 14 posts - 1 through 14 (of 14 total)
  • Author
    Posts
  • #118219
    spiffo
    Participant
    • Topics: 11
    • Replies: 28
    • Total: 39

    OK, I’ve hit a bit of brick wall with this one so hopefully some nice person can shed some light!

    I have a Yamaha DX11 here and I have successfully managed to capture the SysEx it spits out when you change Patches and to route them through to some uiSliders on my panel, but I am having problems trying to extract the 10 Bytes of Data that represent the Patch Name and get them to display in the Panel.

    Below is part of my LUA script which is relevant to building the Patch Name and spitting it out to the Console:

    if size == 101 then

    PatchDataLoaded = midiMessage:getData()

    VCED_Data = midiMessage:getData():getRange(6,94)

    — Extracting the Patch Name Characters & assigning them to variables char1, char2 …etc

    char1 = string.char(VCED_Data:getByte(76))
    char2 = string.char(VCED_Data:getByte(77))
    char3 = string.char(VCED_Data:getByte(78))
    char4 = string.char(VCED_Data:getByte(79))
    char5 = string.char(VCED_Data:getByte(80))
    char6 = string.char(VCED_Data:getByte(81))
    char7 = string.char(VCED_Data:getByte(82))
    char8 = string.char(VCED_Data:getByte(83))
    char9 = string.char(VCED_Data:getByte(84))
    char10 = string.char(VCED_Data:getByte(85))

    getPatchName = char1..char2..char3..char4..char5..char6..char7..char8..char9..char10

    console (“Assigning patch name:”..getPatchName)

    assign_VCED_Values(midiMessage,false)

    else

    console (“Byte Sizes Incorrect”)

    end

    Now as I understand it, string.char converts Hex into ASCII, so that code should construct an ASCII String which is 10 letters long in a Variable called getPatchName?

    Except all I seem to get on the Console and in the uiLabel is 10 Blanks!

    Is there some where else I need to define what Hex Code translates to what ASCII Code, or am I just going about this all the wrong way?

    • This topic was modified 2 months ago by spiffo.
    #118222
    shookingshooking
    Participant
    • Topics: 14
    • Replies: 60
    • Total: 74

    this is what I do

    
      console("processSingleD calling generatePatchPrefix")
    
        getPatchName = generatePatchPrefix(patch, string.format("%.10s", d:getRange(0,10):toString()))
    
        console("[["..getPatchName.."]]")
    

    so i see you know the range of values for your chars. 76 – 85 == 10 chars like my K1r.

    
      console("generatePatchPrefix")
    
        getPatchName = generatePatchPrefix(patch, string.format("%.10s", VCED_Data:getRange(76,10):toString()))
    
        console("[["..getPatchName.."]]")
    

    I _think_ that might work … try it in the console .. SAVE YOUR WORK BEFORE YOU DO IT … I have bitter experience recently of Ctrlr crashing and nuking my Lua.

    #118223
    shookingshooking
    Participant
    • Topics: 14
    • Replies: 60
    • Total: 74

    I typed too fast .. of course you dont need to generate a patch prefix!!

    
    
      console("generatePatchPrefix")
    
        getPatchName = string.format("%.10s", VCED_Data:getRange(76,10):toString())
    
        console("[["..getPatchName.."]]")
    

    sorry about that. so the idea is use the format to restrict to 10 chars (the %.10s)
    grab range of bytes you want … start at 76 and get 10 .. turn that to a string .. put that into variable print variable.

    Hope this works for you

    #118224
    spiffo
    Participant
    • Topics: 11
    • Replies: 28
    • Total: 39

    OK, so that seems a lot more elegant, use string.format to form a 10 Character String from 10 Bytes starting at Byte 76 in my Memory Block called VCED_Data !

    I’m trying to learn this LUA as I go along, basically winging it by copying bits of code, trial & error, and some programming knowledge from way back in school.

    Yep I’ve got the Yamaha MIDI Implementation in front of me, I can follow most of it and with a bit of Trial & Error I’ve managed to work out which Byte is which. I’ve managed to extract the correct Bytes to throw at the right uiSliders. But this afternoon I just couldn’t get that HEX Code converted to ASCII and displayed in a uiLabel, I’ll give your method a go first thing tomorrow.

    Thanks!

    #118240
    dnaldoogdnaldoog
    Participant
    • Topics: 3
    • Replies: 377
    • Total: 380
    • ★★

    I don’t think you need string.format, but it’s certainly interesting and something I didn’t know about.

    getPatchName =VCED_Data:getRange(76,10):toString()

    • This reply was modified 2 months ago by dnaldoogdnaldoog.
    #118246
    shookingshooking
    Participant
    • Topics: 14
    • Replies: 60
    • Total: 74

    depends what you want … in my day job you would be surprised the amount of chaos caused by overwriting bounds.
    Lua and luabind cause rather a lot of havoc to the C/C++ … so I figure explicitly limiting stuff might be ok.
    There again if Lua strings work like more modern languages then it will just keep adding length on until you run out of memory … except often times I am moving data into a memory block and for sure that doesnt keep extending :-))

    >>> console(string.format(“[[%.10s]]”, “hi”))
    [[hi]]

    >>> console(string.format(“[[%.10s]]”, “hiIamAlongstringhaha”))
    [[hiIamAlong]]

    >>> console(string.format(“[[%.10s]]”, “012345678901234567890”))
    [[0123456789]]

    Now since posting this I have had to roll back to 5.3 and it behaves quite differently to 6.x

    Spiffo – when you say “My memory block VCED_Data” can you post how you created it please?

    What I am finding is with 5.3 I have to “loop” whereas with 6.x I can use range operators.
    The key difference is I dont seem able to create a MemoryBlock in 5.3 but can create a CtrlrLuaMemoryBlock.
    The latter appears to behave quite differently to a MemoryBlock — copyTo dont work the same OR I am just confusing myself.

    #118247
    shookingshooking
    Participant
    • Topics: 14
    • Replies: 60
    • Total: 74

    Here’s what I had to hack … man if someone would be so kind to help me build 6.x on Linux I am sure I can help to make it more stable!

    Or how to use MemoryBlock in 5.3 – these CtrlrLuaMemoryBlock behave differently – I am sure I am missing an L somewhere ??

    
    --      /* idx:    0 */  	char	Name[10];		// PatchName 
        local name = ""
    
    --    name = string.format("%.10s", d:getRange(0,10):toString())
    	for i = 0, 9 do
    		console("[[inval_"..i.."]] == [["..d.."]]")
    		console(""..d[1])
        	name = name..string.char(d)
    

    clearly the 6.x method using MemoryBlock is far cleaner than what I am doing with 5.3

    If anyone an spot an obvious mistake I am making and they are near me in UK I will “socially distance” them a beer 🙂

    #118255
    dnaldoogdnaldoog
    Participant
    • Topics: 3
    • Replies: 377
    • Total: 380
    • ★★

    Hi shooking,

    ‘d’ is a MemoryBlock object, so to access each byte, you need d:getByte(i) not d[ i ] the latter being a reference to an index of a non-existent lua table.

    
    d=MemoryBlock("68 69 49 61 6D 41 6C 6F 6E 67 73 74 72 69 6E 67 68 61 68 61")
    
       name = string.format("%.10s", d:getRange(0,10):toString())
    
    console(name) --hiIamAlong
    
    	for i = 0, 9 do
    		console("[[inval_"..i.."]] == [["..d:getByte(i).."]]")
    		console(""..d:getByte(i))
        	name = name..string.char(d:getByte(i))
    end
    
    console(name) -- hiIamAlonghiIamAlong
    

    Also in lua, you can do

    console(String(string.sub("hiIamAlongstringhaha",1,10))) instead of ` console(string.format(“[[%.10s]]”, “hiIamAlongstringhaha”)) but I guess they both produce the same output.

    • This reply was modified 2 months ago by dnaldoogdnaldoog.
    #118256
    dnaldoogdnaldoog
    Participant
    • Topics: 3
    • Replies: 377
    • Total: 380
    • ★★

    Hi shooking,

    copyTo and copyFrom seem to crash Ctrlr.

    I would use ‘append`

    d=MemoryBlock("68 69 49 61 6D 41 6C 6F 6E 67 73 74 72 69 6E 67 68 61 68 61")
    e=MemoryBlock()
    
    e:append(d)
    console("size\t"..e:getSize())
    
    size   20
    

    I think CtrlrLuaMemoryBlock is deprecated, but not sure what that really means.

    • This reply was modified 2 months ago by dnaldoogdnaldoog.
    #118272
    shookingshooking
    Participant
    • Topics: 14
    • Replies: 60
    • Total: 74

    So what I found is in the 6.x version (which I was using thinking latest is greatest) the copyTo etc can work.
    I will try the append.
    Right now with my debugging hints I can see my 5.x panel is failing on what seems to be 6.x specific stuff .. bummer.

    In process of getting my head around it, lighting BBQ, drinking beer and cooking some seriously seasoned chicken – from my Miniaktools secret lair I can use my PC and look out at progress from my pseudo pit …

    Really want to get this memory block peacefully coexisting with MidiData.

    #118273
    shookingshooking
    Participant
    • Topics: 14
    • Replies: 60
    • Total: 74

    what’s smart way of appending a range?
    So I read in raw Sysex from K1r.
    I then strip of the first header 8 bytes (because I can regenerate those), the last but one and F7 byte (checksum and trailing)

    so my MemoryBlocks are what 10 bytes smaller than the raw sysex.

    I just want to take the range 0, 8 [[ from 0 for 8 bytes]] from original midiMessage.
    Then I want to create a block with the residual – 2.
    And from there on I want to reference new blocks as 0 for 1st byte (ie the first char of the name).

    This worked in 6.0 … but then I hit various snags — backporting to 5.3 is messing with my head 🙂

    #118274
    shookingshooking
    Participant
    • Topics: 14
    • Replies: 60
    • Total: 74

    zB does this seem legitimate?

    
                local d1 = MemoryBlock()
    	    d1:append(d:getRange(0, gMULTIPLE_SINGLE_SYSEX_TRAN))
                
                local d2 = d:getRange(gMULTIPLE_SINGLE_SYSEX_TRAN, gMULTIPLE_SINGLE_SYSEX_TRAN)
                local d3 = d:getRange(2 * gMULTIPLE_SINGLE_SYSEX_TRAN, gMULTIPLE_MULTI_SYSEX_TRAN)
    

    ie I am testing the append range of d into empty d1 – you see the way I did it in 6.x and it seemed to work (for d2 and d3)

    #118276
    shookingshooking
    Participant
    • Topics: 14
    • Replies: 60
    • Total: 74

    Ah … I dont mean to contradict you my friend but I will – because clearly I didnt share everything with you.

    I am creating a Multi dimensional array

    
        SINGLE_SYSEX_STORAGE_SIZE = 88
        g_singlePatch = {}
        for i = 0, 63 do
    --[[
    		version 6 has a true parameter, 5 does not
    --        g_singlePatch = MemoryBlock(SINGLE_SYSEX_STORAGE_SIZE, true)
    --]]
            g_singlePatch = MemoryBlock(SINGLE_SYSEX_STORAGE_SIZE)
        end
    
    --
    --  32 slots for multis
    --  deliberately starting from 0 - could start from 64? Examine sysex and make decision
    --  recall the number == patch, so no need to store header nor F7
        g_multiPatch = {}
        -- let store it as 32
        -- note 76 data -- strip of Sysex Header and F7
        MULTI_SYSEX_STORAGE_SIZE = 76
        for i = 0, 31 do
    --[[
    		version 6 has a true parameter, 5 does not
    --        g_multiPatch = MemoryBlock(MULTI_SYSEX_STORAGE_SIZE, true)
    --]]
            g_multiPatch = MemoryBlock(MULTI_SYSEX_STORAGE_SIZE)
        end
    

    You can see my my comments I am pulling what’s left of my hair out 🙂
    So I read in d =midiMessage:getData

    We all agree this has MemoryBlock type semantics.
    But see later I want to “copyTo” .. and in 6.x this works great.
    But in 5.3 it doesnt seem to (or I am doing it wrong).

    So I process according to this stack:

    
    05/08/20 18:49:27       [FILE: [string "requestSinglePatch"]]:          Line: 8         FUNC:
    05/08/20 18:49:27       [TRACEBACK]
    05/08/20 18:49:27       [FILE: [string "handlePanelMidiMessage"]]:              Line: 11                FUNC:
    05/08/20 18:49:27       [Handling sysex size 97 bytes]
    05/08/20 18:49:27       [TRACEBACK]
    05/08/20 18:49:27       [FILE: [string "handleKawaiSysex"]]:            Line: 20                FUNC: handleKawaiSysex
    05/08/20 18:49:27       [FILE: [string "handlePanelMidiMessage"]]:              Line: 66                FUNC:
    05/08/20 18:49:28       [Handling size 97 bytes.]
    05/08/20 18:49:28       [TRACEBACK]
    05/08/20 18:49:28       [FILE: [string "processSingleD"]]:              Line: 303               FUNC: processSingleD
    05/08/20 18:49:28       [FILE: [string "handleKawaiSysex"]]:            Line: 129               FUNC:
    05/08/20 18:49:28       [FILE: [string "handlePanelMidiMessage"]]:              Line: 66                FUNC:
    05/08/20 18:49:28       [TRACEBACK]
    05/08/20 18:49:28       [FILE: [string "processSingleD"]]:              Line: 4         FUNC: validateSysexHeader
    05/08/20 18:49:28       [FILE: [string "processSingleD"]]:              Line: 305               FUNC:
    05/08/20 18:49:28       [FILE: [string "handleKawaiSysex"]]:            Line: 129               FUNC:
    05/08/20 18:49:28       [FILE: [string "handlePanelMidiMessage"]]:              Line: 66                FUNC:
    05/08/20 18:49:33       [d is not empty]
    05/08/20 18:49:38       [TRACEBACK]
    05/08/20 18:49:38       [FILE: [string "processSingleD"]]:              Line: 50                FUNC: process_one_single
    05/08/20 18:49:38       [FILE: [string "processSingleD"]]:              Line: 332               FUNC:
    05/08/20 18:49:38       [FILE: [string "handleKawaiSysex"]]:            Line: 129               FUNC:
    05/08/20 18:49:38       [FILE: [string "handlePanelMidiMessage"]]:              Line: 66                FUNC:
    05/08/20 18:49:38       [TRACEBACK]
    05/08/20 18:49:38       [FILE: [string "generatePatchPrefix"]]:         Line: 3         FUNC: generatePatchPrefix
    05/08/20 18:49:38       [FILE: [string "processSingleD"]]:              Line: 77                FUNC:
    05/08/20 18:49:38       [FILE: [string "processSingleD"]]:              Line: 332               FUNC:
    05/08/20 18:49:38       [FILE: [string "handleKawaiSysex"]]:            Line: 129               FUNC:
    05/08/20 18:49:38       [FILE: [string "handlePanelMidiMessage"]]:              Line: 66                FUNC:
    05/08/20 18:49:38       [TRACEBACK]
    05/08/20 18:49:38       [FILE: [string "handleKawaiSysex"]]:            Line: 6         FUNC: bankChange
    05/08/20 18:49:38       [FILE: [string "handleKawaiSysex"]]:            Line: 139               FUNC:
    05/08/20 18:49:38       [FILE: [string "handlePanelMidiMessage"]]:              Line: 66                FUNC:
    05/08/20 18:49:38       [TRACEBACK]
    05/08/20 18:49:38       [FILE: [string "processSourceMode"]]:           Line: 11                FUNC:
    

    And if you saw my earlier post this is a developing stack of what I am doing.

    So hopefully one can see I request a single
    The Sysex I send out is caught by my handleMidiMessage.
    It filters based on size then header content.
    And dispatches to handleKawaiSysex because it has that manufactures reserved ID.
    We see 97 bytes come in … so we go to next function in the stack ..processSingleD — because this 97 is the exact size of a SYSEX dump for an individual single.

    And one can see further this calls a method in same file validateSysexHeader. It’s good.
    So then we drop back into processSingleD which calls process_one_single. (line 50 of processSingleD).
    He generatepathcPrexi and eventually that cpmpletes, pops stakc, pops state and I am done.

    The complexity that you couldnt have seen

    handlePandelMidiMessage … d is == MidiMessage:getData()
    that is passed into handleKawaiSysex

    
               end
            elseif handleKawaiSysex(d, size, false) == true then
                -- cool it worked
                return 1
            else
    

    who then passes this (via my debug we can see)

    
    05/08/20 18:49:28       [FILE: [string "handleKawaiSysex"]]:            Line: 129               FUNC:
    ...
    
           elseif size == gSINGLE_SYSEX_TRAN then
    
                debugConsole("received single single")
    
                worked = processSingleD(d, true)   <<<<<<< this is line 129
    
                if worked == true and fromFile == true then
                    -- send to synth
                   	utils.warnWindow("\n\nINFO", "About to load Single into K1.")
                    console("sending 1")
                    panel:sendMidiMessageNow(CtrlrMidiMessage(d))
                end
                debugConsole("Endreceived single single")
                local bias = d:getByte(7)
                bankChange(bias)
            end
        end
    

    so d is still a form of MidiMessage but then the fun starts
    Here I convert the subset into a Lua table .. so now I do need the square brackets

    
    
    function processSingleD(--[[ CtrlrLuaMemoryBlock --]] d,
            --[[ bool --]] singlePatch )
        console("in processSingleD")
    	g_debugFile = openDebugFile()
    	whereAmI(g_debugFile, __DFUNC__())
        debugConsole("in processSingleD")
        if validateSysexHeader(d, singlePatch) == false then
            debugConsole("invalid sysex header")
            return false
        end
    
    	debugConsole("single sysex header was valid", true)
    
        if singlePatch == true then
            debugConsole("Single")
            local size = d:getSize()
            local patch = d:getByte(7)
            debugConsole(""..patch)
            console("single "..patch)
            local lp
    
            -- skip the F0 
            -- first 8 bytes and we dont and the F7 and index is a 0 not 1
    		debugConsole("about to copyTo", true)
    
    		for i=0, SINGLE_SYSEX_STORAGE_SIZE -1 do
    			g_singlePatch[patch] = d:getByte(8 + i)
    		end
    
            debugConsole(string.format("Single %d", size))
            debugConsole(string.format("Single %d", g_singlePatch[patch]:getSize() ))
    

    and from now on I need to not use getByte … well maybe I cna use it but it doesnt seem to work because I am a 2 dimensional MemoryBlock.

    Simply to say there was no way you could have know that – and this explains why d[ noti ] references noti byte from d. It’s a MeoryBlock that contains wnother memory block

    
    >>> console(what(g_singlePatch[0]))
    Object type [MemoryBlock]
    -----------------------------------------------------------------
    
    Members:
    	                       getData:	function
    	                   setBitRange:	function
    	                       getByte:	function
    	             loadFromHexString:	function
    	                   toHexString:	function
    	               insertIntoTable:	function
    	                       setSize:	function
    	                      fillWith:	function
    	                        insert:	function
    	                       setByte:	function
    	                       getSize:	function
    	                      getRange:	function
    	                 removeSection:	function
    	               createFromTable:	function
    	                      swapWith:	function
    	                    ensureSize:	function
    	                   getBitRange:	function
    	                        copyTo:	function
    	                   replaceWith:	function
    	                        __init:	function
    	                      copyFrom:	function
    	                      toString:	function
    	                        append:	function
    	            fromBase64Encoding:	function
    	              toBase64Encoding:	function
    	                    toLuaTable:	function
    
    Attributes:
    
    -----------------------------------------------------------------
    Object type [MemoryBlock]
    -----------------------------------------------------------------
    
    Members:
    	                       getData:	function
    	                   setBitRange:	function
    	                       getByte:	function
    	             loadFromHexString:	function
    	                   toHexString:	function
    	               insertIntoTable:	function
    	                       setSize:	function
    	                      fillWith:	function
    	                        insert:	function
    	                       setByte:	function
    	                       getSize:	function
    	                      getRange:	function
    	                 removeSection:	function
    	               createFromTable:	function
    	                      swapWith:	function
    	                    ensureSize:	function
    	                   getBitRange:	function
    	                        copyTo:	function
    	                   replaceWith:	function
    	                        __init:	function
    	                      copyFrom:	function
    	                      toString:	function
    	                        append:	function
    	            fromBase64Encoding:	function
    	              toBase64Encoding:	function
    	                    toLuaTable:	function
    
    Attributes:
    

    and most of the above methods, like you said, are suspect. ie copyTo should work but it doesnt. But on 6.x is does 🙂

    I am hence using old school scalars to work with my vectors.

    When I tried

    
    	local	name=""
    	for i = 0, 9 do
        	name = name..string.char(d)
    		if d == d:getByte(i) then
    			console("d is same as d:getByte(i)")
    		else
    			console("d is DIFFERENT as d:getByte(i)")
    		end
    	end
    

    it crashes because for sure dLgetByte(i) is not what one expects
    And when I comment it out my code works again

    
    	local	name=""
    	for i = 0, 9 do
        	name = name..string.char(d)
    --[[
    		if d == d:getByte(i) then
    			console("d is same as d:getByte(i)")
    		else
    			console("d is DIFFERENT as d:getByte(i)")
    		end
    --]]
            end
    
    #118277
    shookingshooking
    Participant
    • Topics: 14
    • Replies: 60
    • Total: 74

    Hey dnaldoog … I thank you from the bottom of my heart (if I have one :-()

    So once I realized the semantics of my d -> d … well I renamed them d, mb_d and used d:getByte(i) v mb_d.

    What do you know … my 5.3 seems to be working very similar to 6.x before it crashed and stole my Lua.

    Chicken and more beer awaits but thank the Lord, and you, that I found my logic errors.

    I do hope there is an easier way to get the debug like I showed in another post.
    BUT it did help to track down this issue.

    Thanks again whichever continent you are on .. I have to figure it’s the other side of The Pond 🙂
    Cheer and now time to reflect on events of 75 years ago.

Viewing 14 posts - 1 through 14 (of 14 total)
  • You must be logged in to reply to this topic.
There is currently 0 users and 29 guests online
No users are currently active
Forum Statistics
Threads: 2,394, Posts: 16,752, Members: 59,355
Most users ever online was 12 on January 22, 2019 3:47 pm
Do NOT follow this link or you will be banned from the site!