Home › Forums › General › Using Ctrlr › Demo panel for MIDI receive/transmit routines
- This topic has 70 replies, 4 voices, and was last updated 5 years, 7 months ago by
human fly.
-
AuthorPosts
-
October 11, 2017 at 1:36 pm #73155
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)
October 12, 2017 at 6:38 am #73156here’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.October 12, 2017 at 8:00 am #73159here’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 5 years, 7 months ago by
human fly.
Attachments:
You must be logged in to view attached files.October 12, 2017 at 2:25 pm #73163This 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 🙂
October 12, 2017 at 6:09 pm #73164thanks; 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’.October 13, 2017 at 8:04 am #73181‘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.October 13, 2017 at 8:24 pm #73183>>skip
-
This reply was modified 5 years, 7 months ago by
human fly.
October 13, 2017 at 8:43 pm #73185>>skip
October 13, 2017 at 8:53 pm #73186in 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 datasetPatch = 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.
October 14, 2017 at 6:25 am #73188there 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 🙂
October 14, 2017 at 8:45 am #73189meanwhile, 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.October 14, 2017 at 10:57 am #73192i 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.October 15, 2017 at 9:55 am #73200anyone 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.
October 15, 2017 at 10:28 am #73201This 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.October 15, 2017 at 10:40 am #73202and 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.
;-Dedit: *here* is precisely the issue i’m coming up against:
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.October 15, 2017 at 2:28 pm #73204Hi 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
October 15, 2017 at 2:38 pm #73205Or 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
October 15, 2017 at 6:09 pm #73206😀 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?)October 15, 2017 at 6:31 pm #73207very 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.October 15, 2017 at 8:22 pm #73209just 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 = crashAttachments:
You must be logged in to view attached files. -
This reply was modified 5 years, 7 months ago by
-
AuthorPosts
- The forum ‘Using Ctrlr’ is closed to new topics and replies.