Demo panel for MIDI receive/transmit routines

Home Forums General Using Ctrlr Demo panel for MIDI receive/transmit routines

Viewing 20 posts - 1 through 20 (of 71 total)
  • Author
    Posts
  • #73155
    human fly
    Participant
      • Topics: 124
      • Replies: 1070
      • Total: 1194
      • ★★★★

      thought for today (before my next Ctrlr session):
      i want to put together a little demo panel to represent a
      ‘standard’ 2-way MIDI communication setup, that can easily
      be adapted for any device, with visual feedback in the panel
      to demonstrate it working.

      it’s something i need to think about in isolation from the
      rest of my panel project at this point.

      suggestions? what existing Lua do i need?
      i’ve been avoiding dealing with this because it involves
      having tables of all parameters, and i haven’t quite sorted
      out that listing yet.

      i’m going to look at the ‘midiReceive’ methods more closely,
      and build a little panel with 20 parameters, and hopefully
      a ‘virtual device’ with a patchbank, for the ‘panel’ to interface
      with.

      (thinking about it from newb’ point of view)

      #73156
      human fly
      Participant
        • Topics: 124
        • Replies: 1070
        • Total: 1194
        • ★★★★

        here’s a first simple panel, with a ctrlr panel side,
        and an ‘external device’ side. doesn’t do anything yet,
        it’s just a mock-up with 10 parameters.

        need to give it a kind of ‘sysex’ data and work out
        how it’s going to work next.

        Attachments:
        You must be logged in to view attached files.
        #73159
        human fly
        Participant
          • Topics: 124
          • Replies: 1070
          • Total: 1194
          • ★★★★

          here’s a quick v02 – ‘save’ panel side has a method that
          collects the panel values, and puts data on a ‘lcd’ label
          at the bottom. but it crashes the 1st time it runs, and
          if you recompile it, it does send something to the lcd.
          (nothing else does anything yet – this is a quick attempt
          to collect data from the panel faders)

          edit: skip to v03(where you can click the Data box to
          delete contents)

          • This reply was modified 6 years, 5 months ago by human fly.
          Attachments:
          You must be logged in to view attached files.
          #73163
          Icchan
          Participant
            • Topics: 0
            • Replies: 2
            • Total: 2

            This is exactly what this projects needs more. Good examples that limit themselves to one specific area in simple way.

            I’ve wanted to use this project to create a control panel for my Yamaha P50m piano module that has a ton of undocumented sysex commands. I’ve reverse engineered a lot of it, but since Yamaha requires you to add checksum to any sysex command, it’s not so easy to interact with it using just simple saved commands.

            thanks, and I hope you get onwards with your example so the threshold of using CTRLR gets lower 🙂

            #73164
            human fly
            Participant
              • Topics: 124
              • Replies: 1070
              • Total: 1194
              • ★★★★

              thanks; i’m hoping a few of the old hands will drop by
              to help this along.

              the methods and info are all up there, in existing panels,
              but i feel the need to separate it out so i can get my head
              round it.
              – – – –
              one problem here of course is that midiMessage commands are
              send externally over MIDI, so this has to come up with something
              to sidestep that, if it’s to send data to a ‘virtual external device’.

              #73181
              human fly
              Participant
                • Topics: 124
                • Replies: 1070
                • Total: 1194
                • ★★★★

                ‘morning.. here’s today’s installment, v04:
                still not got very far – now has randomising to generate new data
                quickly, and i fixed the ‘save’ method that collects data to the
                screen at the bottom – this still isn’t doing what i expected but
                it does return new data. so it’s more of a demo of those at the
                moment, along the way. orange buttons work. there’s an ‘info’
                method for dev’notes.

                Attachments:
                You must be logged in to view attached files.
                #73183
                human fly
                Participant
                  • Topics: 124
                  • Replies: 1070
                  • Total: 1194
                  • ★★★★

                  >>skip

                  • This reply was modified 6 years, 5 months ago by human fly.
                  #73185
                  human fly
                  Participant
                    • Topics: 124
                    • Replies: 1070
                    • Total: 1194
                    • ★★★★

                    >>skip

                    #73186
                    human fly
                    Participant
                      • Topics: 124
                      • Replies: 1070
                      • Total: 1194
                      • ★★★★

                      in the MKS-50 Advanced bpanelz by layzer/bomma72, there’s a
                      method called ‘setPatch’ that seems to be the basis of a
                      typical sysex receive operation.

                      after a dump request has been sent to the device, this is
                      used to check size and identify the type of data dump.
                      in this case, whether it is Tone or Patch data

                      setPatch = function(midiMessage)
                      
                      s = midiMessage:getSize()
                      if s == 54 then
                      	assignToneValues(midiMessage)  
                      	end
                      
                      if s == 31 then
                      	assignPatchValues(midiMessage)  
                      	end
                      end

                      assignToneValues and assignPatchValues are 2 functions tacked
                      onto the end of the method, as:

                      function assignToneValues(midiMessage)
                      	
                      	programData = midiMessage:getLuaData()
                      
                      	--console ("RAW DATA: ")
                      	--console (programData:toHexString(1))
                      	
                      	panel:getModulatorByName("DcoEvMd"):setValueMapped(programData:getByte(7), true)
                      	panel:getModulatorByName("VcfEvMd"):setValueMapped(programData:getByte(8), true)
                      
                      etc...
                      	panel:getModulatorByName("BndRange"):setModulatorValue(programData:getByte(42), false, false, true)
                      	pName = string.format("%s%s%s%s%s%s%s%s%s%s",
                      			TranslateChar (string.format (programData:getByte(43), number )),
                      			TranslateChar (string.format (programData:getByte(44), number )),
                      
                      etc..
                      
                      end
                      
                      function assignPatchValues(midiMessage)
                      	
                      	programData = midiMessage:getLuaData()
                      
                      	--console ("RAW DATA: ")
                      	--console (programData:toHexString(1))
                      
                      	tNumber = string.format("%.2x",programData:getByte(7))
                      	KeyLow =  string.format("%.2x",programData:getByte(8))
                      	KeyHigh = string.format("%.2x",programData:getByte(9))
                      
                      etc...
                      	
                      end

                      so programData = midiMessage:getLuaData() creates a ?memory block?

                      and then bytes can be accessed as items, and values used to set panel
                      modulator values, eg:

                      panel:getModulatorByName("DcoEvMd"):setValueMapped(programData:getByte(7),
                      true)

                      parameter data starts at byte7 -previous 6 bytes are the sysex header.

                      #73188
                      human fly
                      Participant
                        • Topics: 124
                        • Replies: 1070
                        • Total: 1194
                        • ★★★★

                        there is this also, for sending a patch to the device:

                        --
                        -- Called when a modulator value changes
                        --
                        
                        SendFullTone = function(modulator, newValue)
                        
                        if tChar ~= nil then
                        
                        	label = panel:getModulatorByName("lblPhTtl"):getComponent()
                        	PatchName = label:getProperty("uiLabelText")
                        
                        	if PatchName == "" then 
                        		PatchName = tostring(pNumber) 
                        		label:setPropertyString ("uiLabelText", PatchName)
                        	end
                        	
                        
                        	if PatchName ~= "*Roland MKS-50*" then
                        
                        		TransName = ""
                        		addspace = 0
                        		b = 0
                        
                        		for l=1,10 do
                        
                        			char = string.sub(PatchName,l,l) 
                        
                        			if char=="%" then char="@" end -- % causes issues. 
                        			charNum = TranslateStr(string.format(char))
                        
                        			if tonumber(charNum) > 63 then -- this is for special charicters that are skipped.
                        				addspace = addspace + 1
                        			else
                        				TransName = string.format("%s%s", TransName, string.format(" %.2x", charNum))	
                        			end
                        
                        		end
                        		
                        		while b < addspace do
                        			TransName = string.format("%s%s", TransName, string.format(" %.2x", 62)) -- adding blank spaces at the end if characters are not available.
                        			b = b + 1
                        		end
                        
                        		---------------- Tone Transmit ------------------
                        
                        		PatchCommand = "F0 41 35 00 23 20 01"
                        		PatchCommand = AddHexCommand("DcoEvMd", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("VcfEvMd", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("VcaEvMd", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("DcoPuls", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("DcoSaw", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("DcoSub", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("DcoRnge", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("DcoSbLv", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("DcoNse", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("VcfHpf", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("ChrsOF", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("DcoLfo", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("DcoEnv", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("DcoAftr", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("DcoPwm", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("DcoPwRt", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("VcfFrq", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("VcfRes", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("VcfLfo", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("VcfEnv", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("VcfFolw", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("VcfAftr", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("VcaLvl", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("VcaAftr", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("LfoRate", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("LfoDly", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("EnvT1", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("EnvL1", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("EnvT2", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("EnvL2", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("EnvT3", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("EnvL3", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("EnvT4", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("EnvFolw", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("ChrsRt", tostring(PatchCommand))
                        		PatchCommand = AddHexCommand("BndRange", tostring(PatchCommand))
                        
                        		PatchCommand = string.format("%s%s%s", PatchCommand, TransName, " F7")
                        
                        		panel:sendMidiMessageNow(CtrlrMidiMessage(PatchCommand))
                        
                        	end
                        
                        end
                        
                        end

                        so this shows how the outgoing bulk message is put together
                        -and presumably would let you write *.syx files for a patch
                        library.
                        don’t yet understand ‘PatchCommand = string.format(..’ etc.
                        what is "%s%s%s"?

                        fascinating stuff for the midi fan. apologies if this is longwinded 🙂

                        #73189
                        human fly
                        Participant
                          • Topics: 124
                          • Replies: 1070
                          • Total: 1194
                          • ★★★★

                          meanwhile, this now produces the hex bytes correctly.
                          had omitted ‘string.format(%..’ etc.

                          preset buttons will send some set values to faders.
                          now have to make those set values ‘luaData’ blocks
                          somehow, that can be written to.

                          (got rid of the 2nd ‘extDevice’ for the time being)

                          this is a bit of a detour from the original purpose,
                          to look at how the datadump is built (‘duh’ mode).

                          edit: i think the crash error is a conflict after
                          modulator names have been used to assign values.
                          edit2: yes, just checked: the presets work when
                          it opens, but not after ‘save’ has been used, bcs
                          that method assigns those variable names as values.
                          (i think..)
                          edit3: just changed the variable names in the ‘save’
                          method, adding ‘val_’ as a prefix to all of them,
                          and it fixed the ‘preset’ crashing.

                          Attachments:
                          You must be logged in to view attached files.
                          #73192
                          human fly
                          Participant
                            • Topics: 124
                            • Replies: 1070
                            • Total: 1194
                            • ★★★★

                            i just tried to concatenate strings that i’m sending
                            to text labels, containing hexdata for values. seems
                            to do something…
                            edit: but it is outputting gibberish. doesn’t correspond
                            to what’s in the ‘lcds'(labels) – so it shouldn’t be
                            ‘tostring’..

                            function buildBankA()
                            --concatenate strings
                            local data1=panel:getComponent("lcd_presetData1"):getPropertyString("uiLabelText")
                            local data2=panel:getComponent("lcd_presetData2"):getPropertyString("uiLabelText")
                            local data3=panel:getComponent("lcd_presetData3"):getPropertyString("uiLabelText")
                            local data4=panel:getComponent("lcd_presetData4"):getPropertyString("uiLabelText")
                            
                            	tabl_bankA = {}
                            
                            	tabl_bankA[1]	= tostring(data1)
                            	tabl_bankA[2]	= tostring(data2)
                            	tabl_bankA[3]	= tostring(data3)
                            	tabl_bankA[4]	= tostring(data4)
                            
                            --concatenate table into single string
                            	DatasConcat = table.concat(tabl_bankA, " ", 1, 4)
                            	
                            --make a memory block from the string
                            	memB = MemoryBlock(DatasConcat)
                            
                            --send it to lcd
                            panel:getComponent("lcd_bankDataA"):setPropertyString("uiLabelText",""..memB:toHexString(1))
                            end
                            Attachments:
                            You must be logged in to view attached files.
                            #73200
                            human fly
                            Participant
                              • Topics: 124
                              • Replies: 1070
                              • Total: 1194
                              • ★★★★

                              anyone able to help with concatenating multiple strings
                              from a table into a single string?
                              seems like a logical way to approach sticking several
                              preset values together to produce ‘bank’ data (?)

                              above does not work.

                              #73201
                              human fly
                              Participant
                                • Topics: 124
                                • Replies: 1070
                                • Total: 1194
                                • ★★★★

                                This is exactly what this projects needs more. Good examples that limit themselves to one specific area in simple way.

                                I’ve wanted to use this project to create a control panel for my Yamaha P50m piano module that has a ton of undocumented sysex commands. I’ve reverse engineered a lot of it, but since Yamaha requires you to add checksum to any sysex command, it’s not so easy to interact with it using just simple saved commands.

                                thanks, and I hope you get onwards with your example so the threshold of using CTRLR gets lower ?

                                sending the checksum is not so difficult, it is a Ctrlr routine,
                                using ‘z(n)’, where n is the number of bytes you want to checksum.

                                #73202
                                human fly
                                Participant
                                  • Topics: 124
                                  • Replies: 1070
                                  • Total: 1194
                                  • ★★★★

                                  and thus, i shall now resort to googling, because it returns
                                  mainly Ctrlr topics from the past, and i guess everyone who’s
                                  been here has got bored of answering the same things over and over.
                                  ;-D

                                  edit: *here* is precisely the issue i’m coming up against:

                                  printing getLuaData() in console

                                  so i guess that the fastest way to get responses about Ctrlr
                                  is to google, using what code terms that are stumping you: it
                                  will probably return a Ctrlr post.

                                  #73204
                                  dnaldoog
                                  Participant
                                    • Topics: 4
                                    • Replies: 480
                                    • Total: 484
                                    • ★★

                                    Hi Human Fly,

                                    This code below works and I think you were on the right track (didn’t know about that table.concat function), but I think the problem was the method getPropertyString – getProperty seems to work though. Also for the sendMidi function I think you wrote Memb, should be memB. Interesting!

                                    function buildBankA()
                                    
                                    --add strings to table
                                    	tabl_bankA = {}
                                    for i=1,4 do
                                    local s=L(panel:getComponent("lcd_presetData"..i):getProperty("uiLabelText"))
                                        table.insert(tabl_bankA,s)
                                    end
                                    --concatenate table into single string
                                    	DatasConcat = table.concat(tabl_bankA, " ")
                                    --	console (String("DatasConcat : "..DatasConcat))
                                    --make a memory block from the string
                                    memB = MemoryBlock(DatasConcat)
                                    
                                    --send it to synth
                                    panel:sendMidiMessageNow(CtrlrMidiMessage(memB))
                                    console(String("memBlock :"..memB:toHexString(1)))
                                    
                                    --send it to lcd
                                    panel:getComponent("lcd_bankDataA"):setPropertyString("uiLabelText",""..memB:toHexString(1))
                                    
                                    end
                                    #73205
                                    dnaldoog
                                    Participant
                                      • Topics: 4
                                      • Replies: 480
                                      • Total: 484
                                      • ★★

                                      Or this, which is much closer to your original code:

                                      
                                      function buildBankA()
                                      
                                      --concatenate strings
                                      
                                      	local data1=panel:getComponent("lcd_presetData1"):getProperty("uiLabelText")
                                      	local data2=panel:getComponent("lcd_presetData2"):getProperty("uiLabelText")
                                      	local data3=panel:getComponent("lcd_presetData3"):getProperty("uiLabelText")
                                      	local data4=panel:getComponent("lcd_presetData4"):getProperty("uiLabelText")
                                      
                                      	tabl_bankA = {}
                                      
                                      	tabl_bankA[1]	= data1 -- tostring() not necessary
                                      	tabl_bankA[2]	= data2
                                      	tabl_bankA[3]	= data3
                                      	tabl_bankA[4]	= data4
                                      
                                      --concatenate table into single string
                                      	DatasConcat = table.concat(tabl_bankA," ")
                                      	console ("DatasConcat : "..DatasConcat)
                                      
                                      --make a memory block from the string
                                      	memB = MemoryBlock(DatasConcat)
                                      
                                      --send it to synth
                                      	panel:sendMidiMessageNow(CtrlrMidiMessage(memB))
                                      	--console("memBlock :"..memB:toHexString(1))
                                      
                                      --send it to lcd
                                      	panel:getComponent("lcd_bankDataA"):setPropertyString("uiLabelText",""..memB:toHexString(1))
                                      
                                      end

                                      panel:sendMidiMessageNow(CtrlrMidiMessage(DatasConcat )) also works, so there’s no need for the MemoryBlock function

                                      #73206
                                      human fly
                                      Participant
                                        • Topics: 124
                                        • Replies: 1070
                                        • Total: 1194
                                        • ★★★★

                                        😀 GREAT ! thank you !
                                        perfect: i now get all my bytes as they should be. excellent.
                                        i’ve just done it the way most resembling my original, so now
                                        i’ll go back and do it the way you suggest. (could you elaborate
                                        on ?macros? s=L(etc. ) )

                                        so i only need to specify start and end with the table if i’m
                                        not concatenating all of it? and ‘data1…4’ are already strings,
                                        so no need for tostring.. and yes i did have ‘MemB’, and it does
                                        make sense to go direct with ‘DatasConcat’. i used the memory block
                                        bit because it was in what i was adapting : -)

                                        it’s the first time i’ve attempted something like this.
                                        along the way i’ve looked at getLuaData/getData again, and that
                                        seems pretty straightforward (hoho, sure i’ll have some problem
                                        there) – i’m wondering if i should just ditch the notion of
                                        using a ‘virtual external device’ for this demo panel, for the
                                        sake of clarity (it means figuring out how to do it, when i
                                        won’t even be using it, as well). any ideas how i might do
                                        a ‘virtual’ getData? (haven’t actually thought of it yet)

                                        ie: the idea there is to achieve transfer/receive without
                                        having an external device connected, of course. so i guess
                                        it needs to be something as close to a midimessage as poss’,
                                        without using that Ctrlr function.(don’t know if you opened
                                        the panel?)

                                        #73207
                                        human fly
                                        Participant
                                          • Topics: 124
                                          • Replies: 1070
                                          • Total: 1194
                                          • ★★★★

                                          very interesting, how you ‘collect’ the table like that,
                                          since they all have the same prefix: you can just append
                                          the number of each using:

                                          for i=1,4 do
                                          local s=L(panel:getComponent("lcd_presetData"..i):getProperty("uiLabelText"))
                                          table.insert(tabl_bankA,s)
                                          end

                                          table.insert(tabl_bankA,s) … waAaah!

                                          anyway: here’s the sorted-out version:

                                          Attachments:
                                          You must be logged in to view attached files.
                                          #73209
                                          human fly
                                          Participant
                                            • Topics: 124
                                            • Replies: 1070
                                            • Total: 1194
                                            • ★★★★

                                            just one little problem remaining: if i try to buildBank
                                            with empty source labels, Ctrlr crashes – see error png –

                                            strange, because it has started doing that since i added
                                            another function elsewhere (a popup menu to select preset
                                            to send – at present it just sends “preset sent” 1..4 to
                                            the various labels) – and i’m fairly sure it didn’t crash
                                            when i tried an ’empty’ buildBank before.

                                            so it needs some contingency for when there’s nothing to
                                            write, i guess. going to try it now with one or more
                                            source slots empty.. no: that’s ok. it’s just if there’s
                                            nothing to write = crash

                                            Attachments:
                                            You must be logged in to view attached files.
                                          Viewing 20 posts - 1 through 20 (of 71 total)
                                          • The forum ‘Using Ctrlr’ is closed to new topics and replies.
                                          There is currently 0 users and 47 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