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: 15
      • Replies: 62
      • Total: 77

      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
      dnaldoog
      Participant
        • Topics: 4
        • Replies: 480
        • Total: 484
        • ★★

        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 3 years, 8 months ago by dnaldoog. Reason: fixed some formatting errors
        • This reply was modified 3 years, 8 months ago by dnaldoog. Reason: add getData() method
        #118903
        damien
        Participant
          • Topics: 15
          • Replies: 62
          • Total: 77

          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
          dnaldoog
          Participant
            • Topics: 4
            • Replies: 480
            • Total: 484
            • ★★

            Ah! realised with midiMessage you need:

            midiMessage:getData():getByte(i)

            added getData() to my first reply

            • This reply was modified 3 years, 8 months ago by dnaldoog.
            #118907
            Possemo
            Participant
              • Topics: 14
              • Replies: 638
              • Total: 652
              • ★★★

              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: 15
                • Replies: 62
                • Total: 77

                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
                dnaldoog
                Participant
                  • Topics: 4
                  • Replies: 480
                  • Total: 484
                  • ★★

                  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: 1
                    • Replies: 54
                    • Total: 55

                    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 3 years, 8 months ago by samoht.
                    #118912
                    samoht
                    Participant
                      • Topics: 1
                      • Replies: 54
                      • Total: 55

                      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 3 years, 8 months ago by samoht.
                      #118914
                      damien
                      Participant
                        • Topics: 15
                        • Replies: 62
                        • Total: 77

                        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
                        dnaldoog
                        Participant
                          • Topics: 4
                          • Replies: 480
                          • Total: 484
                          • ★★

                          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: 15
                            • Replies: 62
                            • Total: 77

                            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: 1
                              • Replies: 54
                              • Total: 55

                              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 3 years, 8 months ago by samoht.
                              • This reply was modified 3 years, 8 months ago by samoht.
                            Viewing 13 posts - 1 through 13 (of 13 total)
                            • The forum ‘Programming’ is closed to new topics and replies.
                            There is currently 0 users and 40 guests online
                            No users are currently active
                            Forum Statistics
                            Threads: 2,495, Posts: 17,374, Members: 77,605
                            Most users ever online was 12 on January 22, 2019 3:47 pm
                            Ctrlr