Storing received sysex dump as memoryblock then process

Home Forums General Programming Storing received sysex dump as memoryblock then process

Viewing 13 posts - 1 through 13 (of 13 total)
  • Author
    Posts
  • #118900
    damien
    Participant
    • Topics: 14
    • Replies: 54
    • Total: 68

    Hi,
    I worked on my panel with a hard coded midi dump message in my global “on received midi” LUA script while my DP4 was out of order. I kept a buffer dump from before the unit failure.

    Now that it’s repaired, I have some problem getting the midi message received by Ctrlr stored as a memoryblock.

    This is the following script on “Called when the panel received a midi message”, I must have something wrong somewhere at the beginning. It used to work when using the hardcoded message I commented :

    
    midiMessageReceived = function(midiMessage)
    
    midiMessageRawSize = midiMessageReceived:getSize()
    MessageType = midiMessageReceived:getByte(5)
    
    if  midiMessageRawSize == 334 and MessageType == 0x25 then   -- determine if the message is Edit Buffer Type hex25 with size 334bytes
    
    t={}
    midiMessage = MemoryBlock()
    -- midiMessage = MemoryBlock([[F0 0F 40 00 00 25 01 00 00 03 02 02 00 05 03 06 0F 07 05 07 02 06 03 06 05 02 00 04 03 06 0F 06 0E 06 06 06 09 06 07 02 00 00 01 02 0F 00 00 03 00 04 08 05 04 04 09 02 05 01 0B 04 0B 00 00 00 07 07 05 00 00 01 0C 01 06 00 00 05 01 00 0A 00 0D 00 01 09 04 04 0B 04 09 00 06 00 01 02 0C 07 0F 00 07 00 03 02 0F 05 0D 07 0F 07 0F 00 03 02 00 01 02 02 0D 05 01 03 02 04 0E 02 0E 01 04 00 04 00 00 02 09 09 0D 00 00 00 0C 02 0D 00 00 01 07 01 03 00 00 00 00 05 0E 0E 0D 02 00 00 06 00 01 03 0F 07 0F 00 07 00 03 02 00 00 00 07 0F 07 0F 00 00 00 00 02 0B 00 0D 02 00 00 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 07 0F 00 00 00 02 00 00 07 0F 07 0F 07 0F 02 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 07 0F 00 00 00 02 00 00 07 0F 07 0F 04 00 00 00 00 00 00 02 00 01 00 00 00 00 01 00 00 00 F7]])
    
    for i=9,
    	midiMessage:getSize()-2,2 do
    	assert(i < midiMessage:getSize())	-- For debugging only
    	msb = bit.lshift(midiMessage:getByte(i),4)
    	lsb = midiMessage:getByte(i+1)
    	total = msb+lsb		-- console(String(string.format("[%d] = %.2X",i,total)))
    	
    	table.insert(t,total)
    end
    
    EditBufferMessage = MemoryBlock()
    EditBufferMessage:createFromTable(t)
    --console(String(EditBufferMessage:toHexString(1)))
    --panel:getLabel("Debug"):setText(EditBufferMessage:toHexString(1))
    
    ActiveUnitDecode(midiMessage)
    BufferPstNameDecode(EditBufferMessage)
    BypassStatusDecode(EditBufferMessage)
    UAAlgoLblDecode(EditBufferMessage)
    UBAlgoLblDecode(EditBufferMessage)
    UCAlgoLblDecode(EditBufferMessage)
    UDAlgoLblDecode(EditBufferMessage)
    ConfigSrcTypeDecode(EditBufferMessage)
    UAAlgoDecode(EditBufferMessage)
    UBAlgoDecode(EditBufferMessage)
    UCAlgoDecode(EditBufferMessage)
    UDAlgoDecode(EditBufferMessage)
    panel:getModulatorByName("ViButComEdit"):getComponent():setValue(1, true)
    end
    
    end

    When I send a request to the Unit, I get the following error:

    At line 8 : string “midiMessageReceived
    Error message : string “midiMessageReceived”:8: attempt to index global ‘midiMessageReceived (a function value)

    I want to store midiMessage (the received dump) as the MemoryBlock to be able after that to process all the different function from it.

    EDIT: I edited my post and it disapeared and there’s no way to bring it back to life. This Edit bug on the forum is horrible…

    Thanks a lot for your help

    Damien

    #118901
    dnaldoogdnaldoog
    Participant
    • Topics: 3
    • Replies: 371
    • Total: 374
    • ★★

    Hi Damien,

    I feel your pain with regards to the edit three times and strike you’re out. If that happens hit the back button on your browser, cut and paste and wait a few hours to re-post. Not familiar with WordPress, but the admins surely could fix that somehow?

    The problem with the code above is you are doing a getSize() on the function name. Also you declare a midiMessage=MemoryBlock() – that would zero out the midiMessage passed into the function.

    I would initialise total outside the loop just to be safe and also I recommend keeping everything local if possible.

    
    midiMessageReceived = function(midiMessage)
    
    local midiMessageRawSize = midiMessage:getSize()
    local MessageType = midiMessage:getData():getByte(5)
    
    if  midiMessageRawSize == 334 and MessageType == 0x25 then   -- determine if the message is Edit Buffer Type hex25 with size 334bytes
    
    local t,total={},0
    --local newMidiMessage = MemoryBlock() don't need this
    for i=9,midiMessageRawSize-2,2 do
    	--assert(i < midiMessage:getSize())	-- For debugging only
    	local msb = bit.lshift(midiMessage:getData():getByte(i),4)
    	local lsb = midiMessage:getData():getByte(i+1)
    	total = msb+lsb		-- console(String(string.format("[%d] = %.2X",i,total)))
    	
    	table.insert(t,total)
    end
    
    EditBufferMessage = MemoryBlock()
    EditBufferMessage:createFromTable(t)
    --console(String(EditBufferMessage:toHexString(1)))
    --panel:getLabel("Debug"):setText(EditBufferMessage:toHexString(1))
    
    ActiveUnitDecode(midiMessage)
    BufferPstNameDecode(EditBufferMessage)
    BypassStatusDecode(EditBufferMessage)
    UAAlgoLblDecode(EditBufferMessage)
    UBAlgoLblDecode(EditBufferMessage)
    UCAlgoLblDecode(EditBufferMessage)
    UDAlgoLblDecode(EditBufferMessage)
    ConfigSrcTypeDecode(EditBufferMessage)
    UAAlgoDecode(EditBufferMessage)
    UBAlgoDecode(EditBufferMessage)
    UCAlgoDecode(EditBufferMessage)
    UDAlgoDecode(EditBufferMessage)
    panel:getModulatorByName("ViButComEdit"):getComponent():setValue(1, true)
    end
    
    end
    
    • This reply was modified 1 week, 3 days ago by dnaldoogdnaldoog. Reason: fixed some formatting errors
    • This reply was modified 1 week, 3 days ago by dnaldoogdnaldoog. Reason: add getData() method
    #118903
    damien
    Participant
    • Topics: 14
    • Replies: 54
    • Total: 68

    thanks dnldoog,
    I’m back for the last stretch in this project.
    I tried what you suggested but get an error :

    Error message: [string “midiMessageReceived”]:19: attempt to call method ‘getByte’ (a nil value)

    My sysex request is going to the unit properly:
    To MIDI output port 0 SysEx Ensoniq 7 bytes F0 0F 40 00 00 15 F7

    And the message is sent back to ctrlr properly :
    From MIDI input port 0 SysEx Ensoniq 334 bytes F0 0F 40 00 00 25 02 00 00 03 04 02 00 05 03 07 02 06 03 03 0A 03 04 02 00 04 0D 06 0F 06 0E 06…

    So it’s probably just a syntax error but cannot find out what’s wrong with it.

    I did a simple request to display the string in the console and get an error for nil value as well:

    midiMessageReceived = function(midiMessage)
    
    local midiMessageRawSize = midiMessage:getSize()
    
    if  midiMessageRawSize == 334  then
    
    console(String(midiMessage:toHexString(1)))
    end
    
    end
    

    It’s probably coming from the very top of the script.

    Any idea about what’s wrong with it? the stripped down version should give at least the sysex message in the console?

    Thanks a lot!

    #118904
    dnaldoogdnaldoog
    Participant
    • Topics: 3
    • Replies: 371
    • Total: 374
    • ★★

    Ah! realised with midiMessage you need:

    midiMessage:getData():getByte(i)

    added getData() to my first reply

    • This reply was modified 1 week, 3 days ago by dnaldoogdnaldoog.
    #118907
    PossemoPossemo
    Participant
    • Topics: 14
    • Replies: 604
    • Total: 618
    • ★★★

    Error message: [string “midiMessageReceived”]:19: attempt to call method ‘getByte’ (a nil value)

    It’s probably coming from the very top of the script.

    The error message tells you that the error is on line 19. Unfortunately, error messages are no always that clear.

    #118908
    damien
    Participant
    • Topics: 14
    • Replies: 54
    • Total: 68

    Well I don’t know what’s happening, it’s more like if the ctrl don’t receive the sysex message.
    Tomorrow I’ll try a simple button that send the dump request message.

    Then display the message received by ctrlr in the console.
    something like :

    midiMessageReceived = function(midiMessage)
    console(String(midiMessage:toHexString(1)))
    end
    

    It should display the sysex message received in the console isn’t it?

    #118909
    dnaldoogdnaldoog
    Participant
    • Topics: 3
    • Replies: 371
    • Total: 374
    • ★★

    Hi Damien,

    That should be:

    
    midiMessageReceived = function(midiMessage)
    console(String(midiMessage:getData():toHexString(1)))
    end
    
    

    I’m surprised adding the additional getData() method didn’t fix the problem on line 19:

    Error message: [string “midiMessageReceived”]:19: attempt to call method ‘getByte’ (a nil value)

    Incidentally you can do midiMessage:getSize() just as in a normal MemoryBlock, but to access data on an incoming MIDI message, you need getData()

    #118910
    samoht
    Participant
    • Topics: 0
    • Replies: 13
    • Total: 13

    Hi Damien, Dnaldoog, Possemo: this is working for me;

    midiMessageReceived = function(midi)�
    
    local s = midi:getSize()
    local Id1 = midi:getLuaData():getByte(5)
    local Id2 = midi:getLuaData():getByte(6)
    �
    if s == 60 then
     	   if Id1 == 0x10 then
        		if Id2 == 0x10
    			then
    				t1Nibbles = midi:getData():getRange(8, 24)
    				--clear()
    			elseif Id2 == 0x11 then
    				t21Nibbles = midi:getData():getRange(8, 24)
    				--clear()
    			elseif Id2 == 0x12 then
    				t3Nibbles = midi:getData():getRange(8, 24)
    				--clear()
    			elseif Id2 == 0x13 then
    				t41Nibbles = midi:getData():getRange(8, 24)
    				--clear()
    			elseif Id2 == 0x14 then
    				t51Nibbles = midi:getData():getRange(8, 24)
    				--clear()
    			elseif Id2 == 0x15 then
    				t61Nibbles = midi:getData():getRange(8, 24)
    				--clear()
    			end
    		end
    	end�
    end --f
    • This reply was modified 1 week, 2 days ago by samoht.
    #118912
    samoht
    Participant
    • Topics: 0
    • Replies: 13
    • Total: 13

    I am new to Lua as well as Ctrlr and Juce. One thing has become clear to me though: you have to find a way, starting in Lua, through Ctrlr and Juce, always in full respect for midi bytes and nibbles and for the quirks of each platform (f.i. a lua “string” apparently is not identical to a Juce “string” and so on) and always paying attention that the roads do not to often end up in “memory full” loops, or worst crashes 🙂

    • This reply was modified 1 week, 2 days ago by samoht.
    #118914
    damien
    Participant
    • Topics: 14
    • Replies: 54
    • Total: 68

    And…

    it’s….

    WORKING!!!!

    midiMessage:getData():getByte(i) was a keypoint but error still occured.
    I messed with the script and removed the “local” tag and it worked.

    So everything is dumped from the unit to ctrlr every parameter are updated.
    I have to think about a way to add a timer between sent messages because the unit is cluttered rapidly.
    Everytime a message is received, processed and complete the unit send an acknowledge “error” message telling the unit is ready for operation again.

    Message received is (my commented console report) :

    
    LUA>> Displays the RAW Received Midi Message
    LUA>> f0 0f 40 00 00 02 00 f7
    LUA>> Displays the Received Midi Message Type in decimal
    LUA>> 2
    LUA>> Displays the MessageErrorCode in decimal
    LUA>> 0
    LUA>> 0 Meaning TX over - Ackowledge (ACK) - No Error

    So I’ll think about a way to wait the ACK message for sending new message to avoid cluttering the input of the DP4.

    Thanks a lot for all your help! I deeply appreciate the support.
    Damien

    #118915
    dnaldoogdnaldoog
    Participant
    • Topics: 3
    • Replies: 371
    • Total: 374
    • ★★

    Hi Damien,

    Great that it’s working.

    So if you need to send an ACK message, but need a delay, just before you send the message try:

    os.execute(sleep(125))

    125=Milliseconds for example.

    Or an example of timer code in this post (with example panel)

    ctrlr.org/forums/topic/midi-out-led/#post-118738

    #118916
    damien
    Participant
    • Topics: 14
    • Replies: 54
    • Total: 68

    For the delay time between messages I went with a setting in the “general” preference pane called:
    Global delay for midi message [ms]

    It’s working great.

    I was talking about waiting the message “ready” FROM the Ensoniq.
    Everytime the unit is ready for a new task it sends a sysex message “I’m ready”:
    f0 0f 40 00 00 02 00 f7

    It’s very useful because sometime it’s still in process so considering this type of flag is a nice tool to avoid errors.

    Thanks!

    #118929
    samoht
    Participant
    • Topics: 0
    • Replies: 13
    • Total: 13

    Damien wrote:

    I messed with the script and removed the “local” tag and it worked.

    Dnaldoog wrote:

    I recommend keeping everything local if possible.

    Sometimes variables need to be global. But this should always be used with caution since they easily cause subtle bugs!

    • This reply was modified 1 week, 1 day ago by samoht.
    • This reply was modified 1 week, 1 day ago by samoht.
Viewing 13 posts - 1 through 13 (of 13 total)
  • You must be logged in to reply to this topic.
There is currently 0 users and 26 guests online
No users are currently active
Forum Statistics
Threads: 2,393, Posts: 16,738, Members: 59,189
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!