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 23, 2017 at 3:22 am #73279
myMethod = function(--[[ CtrlrModulator --]] mod, --[[ number --]] value, --[[ number --]] source) extBank = L(panel:getModulatorByName("lcd_bankDataB"):getComponent():getProperty("uiLabelText")) console("Retrieving external bank : "..extBank) --make a memory block from the string memB = MemoryBlock(extBank) -- this variable is used to send midi???? --check size of received dump local size = memB:getSize() -- same as size=string.len(extBank)??? console("midiMessageReceived: " .. size .. "bytes") if size == 80 then --bank dump console("bank dump detected!") end extBank:gsub("(%w+)",function(c) table.insert(tabl_extBank,c) end) for i,v in ipairs(tabl_extBank) do console("i="..i.." v="..v) end console("size of tabl_extBank="..#tabl_extBank) end
–convert bank to table tabl_extBank = {} for i=1,80 do s=extBank:toHexString(1) table.insert(tabl_extBank,s) end
I think toHexString(1) just dumps a memory block into a string. ‘extBank’ is a string obtained from a uiTextLabel, so it is not a memory block. To convert a string into a table, you would need to split or explode it somehow using a delimiter (like excel does with csv files). The code above gsub(“(%w+)” does a similar thing by ignoring whitespace and just loading the number 0-9 or letter A-F into each element of the table. Not fully tested though π
extBank:gsub("(%w+)",function(c) table.insert(tabl_extBank,c) end)
I found it here.October 23, 2017 at 8:23 pm #73281scary. going to have to get my head round that.
quick recap: i put extBank into memory block memB just so that
i could getSize() on it without it returning a nil error.
trying to (ermm) keep it as similar as possible to what happens
when it’s a Ctrlr midi message. as in (midiMessage).i’m thinking that if i can get all the bytes of the big string
into a table, then it will be easier to get them by index with
getRange() – which has been returning nil errors as well – and
then i can do what i want with them (within the limited capabilities
at my current disposal lol). i’m very heath-robinson/string+sellotape.but this is what happens, isn’t it, when a bulk dump comes in, and
the device, or panel, want to send its little presets into their
little pigeonhole memory slots, and then everyone’s happy. right?hello device, send me your stuff. ok, here it is, do your thing.
ok, thanks. this goes here, this goes here…etc…and this one
goes here, done.mainly called ‘midiMessageReceived’ in most of these panels i look
at. edit: no it, isn’t, i just looked; i can’t remember where i’ve
seen the thing i remember.say, if i had a sysex header in there: ‘f0 41 10 blabla’ and f7 at
the end, on the bulkdata – then i’d want to skip the header and
ender, but all would have an index position, say, in a table(i like
array, that’s cool too – seems people talk about tables here), so
i just want to grab index ranges and send the data to the preset
slots. i think that would do it.(believe it or not, i was trying/achieving text based sequencers
in synthedit with similar techniques – sirsicksik/siksick was the
master of this, but nobody ever understood his prefabs. or his
plugins…)can we skip gsub for the time being? π
October 24, 2017 at 3:28 am #73283Well I never looked at the reason for this function, just focusing on the errors you were dealing with and offering a way of fixing those (particular issues), but it seems that all you are trying to do is process the data coming in from the synth.
I don’t think you need to do all that memoryblock converting or midi:getLuaData():getRange(), gsub() stuff. Needs to be as simple as possible or else all these compilation errors start seeping in as you are finding out.
If you know a certain midi dump will be say 65 bytes long then:
myMidiReceived = function(--[[ CtrlrMidiMessage --]] midi) local s = midi:getSize() if s == 65 then
…now work out a way of writing into the values of a midi:getLuaData():getByte() to various modulator/components (uiSliders uiCombos etc); that magic moment when you see all the sliders change values on screen!
You can do this by mapping the position of each byte in midi:getLuaData():getByte() to a table of modulator/Component names.
This would be the foundation/core of your whole program!!! Everything else should be designed around this central function of Ctrlr π
e.g.
t={ "WG_PITCH_COARSE", -- 0x00 this would be the name of the Modulator/Component "WG_PITCH_FINE", -- 0x01 "any_mod_name_I_choose", -- 0x10 -- <em>54 more elements to be listed here</em> "TV_ENV_SUSTAIN_LEVELβ, -- 0x39 } --pseudo code follows untested!! j=1 for i=5,65-2 do -- 5 could be the offset from the sysex header F0 41 ?? ?? ?? -- -2 = ignore checksum and F7 (in the case of Roland Synths) m=midi:getLuaData():getByte(i) panel:getModulatorByName(t[j]):getComponent():setValue(m,false) j=j+1 end
This is all untested, but hopefully it will help you understand the core idea of getting data out of the D-110 and into ctrlr. π
October 24, 2017 at 7:52 am #73284ok, i see how that last section works – this is ok as long as
all values incoming are ‘literal’, and i don’t have to deal
with any ‘mapped’ offsets ie: pan with midi value 0-14 where it
is displayed as -7<0>+7October 24, 2017 at 9:20 am #73285ok, i see how that last section works β this is ok as long as
all values incoming are βliteralβ, and i donβt have to deal
with any βmappedβ offsets ie: pan with midi value 0-14 where it
is displayed as -7<0>+7As you know, in such a case -7 to +7 are actually the values 0-14 so as far as midi and the D-110 are concerned. It’s only at the interface level that you would need to display -7 – +7 and in fact 0 to the D-110 would be 7 for the control at that address (you know this, but someone else reading this might not). That’s where you would use uiFixedSlider etc.
I suppose there could be some reason to convert the midi values 0,1 to -7, -6 etc in lua (ie sending text to uiLabel), but for pure sending of midi and receiving I don’t think it is necessary π
in practice, i will have to split this read-off of values from
the incoming data whenever i…Sometimes you may want to load every byte into a table and then run various functions on the address stored in the table rather than run a series of if/else on every midi-data-byte. But either would work.
i wanted to play with it without it being a Ctrlr midi
message type β because that seems to require it to be a message
incoming on the midi bus.(if you see what i mean..)Do you mean doing all this without being connected to the D-110? No doubt that makes it a bit more difficult to test, but maybe you could set up a program like Midi-Ox to transmit sysex messages to your panel? π
October 24, 2017 at 6:33 pm #73286yup point/s taken – this little demo panel, though,
is/was merely a test thing – a ‘paraphrasing’, ..a simili !
hard day’s painting&decorating today, so if i recover from
that and get some inspiration, i’ll have a go at getRange().
my 6am sessions are on hold at the moment because i tend to
forget i’m supposed to go to work if i start up Ctrlr πOctober 25, 2017 at 7:35 am #73291tried the last code thing, loads of ways π didn’t compile
– but doesn’t matter: there’s a very nice example in this
tg33 panel that was posted in september, i should be able to
work from that, for the D-110 panel.just for now, i’m going to focus (for the hell of it…but do
i really need to do this? whatever: just want to see how to
do it…) on splitting this big 80’byte’ string into 4 separate
20’byte’ strings, and send them to the labels.
(i realise this has little to do with the midi receive routine,
but it will make sense of this panel ..aargh, getting lost here,
never mind: i’ve found my thing for the D-110, gotta finish that
thing.)October 25, 2017 at 10:13 am #73293this little demo panel, though,
is/was merely a test thing β a βparaphrasingβ, ..a simili !Oh I see, but it’s all very interesting and for me and leads to greater understanding generally. π
October 26, 2017 at 8:44 pm #73297okay, playtime again. had fun trying that untested script:
it made Ctrlr crash in a loop, as i tried it π
so i had to delete Ctrlr roaming settings..anyway: so, inspired by the TG33 midiReceived, i had
another go at splitting the ‘big’ string with getRange()
-so far, just trying to have a look at what can be sent
to console. getting wrong data, evidently. best thing to
do is have a look at the getBank method(annotated, with
all previous junk in it).
nb: the reason i’m trying to go via memory block is that
you can getSize() on it (whereas i couldn’t with other
attempts)it is then able to getRange() – at this point i send each
one to console, and get – ? – wrong data type, anyway.> all i would like to do right now is see the ‘big’ string
split into 4 separate strings – i know this isn’t specifically
hex at this stage, just text.i s’pose i’m mixing stuff up here, aren’t i?
(i need an empty day to get into this properly)October 27, 2017 at 8:22 am #73298Hi there Human Fly,
I have got that code working from above. See panel. Here I am sending a made-up Sysex string …
F0 41 10 16 12 03 00 00 00 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 41 F7
… from MidiOx to trigger the midi received function in the panel using virtual midiports (LoopMidi).
Enjoy!
π
Attachments:
You must be logged in to view attached files.October 27, 2017 at 5:35 pm #73308hey, ok thanks. will load it up in a minute.
here’s another version of what i was doing, from this morning
(see below) – if you look at the getBank method, you’ll see what
i’ve been trying: managed to generate two separate strings from
the ‘big’ one – read to console only atm. but for some reason,
i don’t get all four, and didn’t have time to check the bytes to
see if they corresponded – hope it makes sense if you look at it.need to tidy this up before i try again(loads of commented-out
stuff in there, things i tried/failed with)Attachments:
You must be logged in to view attached files.October 27, 2017 at 6:52 pm #73310mmm? i tried your panel – my onboard midi interface is loopbe1, how
i link to midiox. didn’t get anything there yet. but i’m going to
look at it more closely.can we look at this splitting of a string into 4 strings thing?
i call the string content ‘extBank’, then i make a memory block
of that, so i can getSize – the way you can with a midi message –
(not essential, but just so i can ‘tick that box’)if i do memB toHexString, i don’t get hex data, i get something
else – so i’ve skipped that.instead, i’m doing:
prog1Data = memB:getRange(1,20) preset1 = prog1Data:toHexString(1) console("preset1 :"..preset1)
and the same, through prog2data, prog3data, prog4data.
what i get back is prog1 has 20 bytes, but starts at
byte2 (misses the first one), and then all the rest of
the data is in prog2, and prog3 + 4 have nothing.
and i’m not getting any errors.
confoooosed πthinking: if i can get the ‘data’ with these, it should
be possible to send it to the label slots that the presets
refer to…. -?- (hey just for kicks)October 27, 2017 at 7:00 pm #73311i will say that i’m liking the tg33 panel midi received method.
Peter Scheidt says that calling modulators by VST Index was his
best option – i do like the idea of having a common ID system:
it means building the entire thing and numbering it before you
can test – which is a bit daunting when you haven’t yet attributed
all of your VST Index #slook at the D-110 .. when you’ve got a synth wave selected, it’s
the same MIDI parameter # as the PCM Bank: you end up with 2 objects
to select the same parameter, which will necessarily have different
VST index numbers, so when you give a quick headcount of your parameters,
*it won’t correspond* aargh: i should know by now how many parameters
each partial has, i think it’s 58, not counting the Common params.
um, i’d like to sidestep that for the time being; i’m still pondering
some layout issues on that one.October 27, 2017 at 9:04 pm #73312yesss. grrrrr ! π sussed it. getRange numbers are not
start and end, it’s start, the the number of items. so
it’s done like this: (note i had to specify start minus 1)
`prog1Data = memB:getRange(1-1,20)
preset1 = prog1Data:toHexString(1)
console(“preset1 :”..preset1)prog2Data = memB:getRange(21-1,20)
preset2 = prog2Data:toHexString(1)
console(“preset2 :”..preset2)prog3Data = memB:getRange(41-1,20)
preset3 = prog3Data:toHexString(1)
console(“preset3 :”..preset3)prog4Data = memB:getRange(61-1,20)
preset4 = prog4Data:toHexString(1)
console(“preset4 :”..preset4)`and that produces (in console):
LUA>> midiMessageReceived: 80bytes
LUA>> bank dump detected!
LUA>> preset1 :6f 6e 65 20 20 20 20 20 20 20 2a 33 59 64 34 00 78 7f 62 4e
LUA>> preset2 :74 77 6f 20 20 20 20 20 20 20 74 3b 64 59 08 51 7f 7c 3c 2b
LUA>> preset3 :74 68 72 65 65 20 20 20 20 20 55 12 7f 3b 0f 11 2b 60 58 19
LUA>> preset4 :66 6f 75 72 20 20 20 20 20 20 55 5d 3b 2e 69 51 7f 7c 3c 2bhe he.
(‘code’ buttons not working tonight)
October 28, 2017 at 7:57 am #73313more: have tidied up script into a re-usable:
function restoreBank() -- This variable stops index issues during panel bootup if panel:getRestoreState() == true or panel:getProgramState() == true then return end -- retrieving BankA bankA = L(panel:getModulatorByName("lcd_bankDataA"):getComponent():getProperty("uiLabelText")) local memB = MemoryBlock(bankA) local size = memB:getSize() if size == 80 then local prog1Data = memB:getRange(0,20) local preset1 = prog1Data:toHexString(1) local prog2Data = memB:getRange(20,20) local preset2 = prog2Data:toHexString(1) local prog3Data = memB:getRange(40,20) local preset3 = prog3Data:toHexString(1) local prog4Data = memB:getRange(60,20) local preset4 = prog4Data:toHexString(1) panel:getComponent("lcd_presetData1"):setPropertyString("uiLabelText",""..preset1) panel:getComponent("lcd_presetData2"):setPropertyString("uiLabelText",""..preset2) panel:getComponent("lcd_presetData3"):setPropertyString("uiLabelText",""..preset3) panel:getComponent("lcd_presetData4"):setPropertyString("uiLabelText",""..preset4) end end
here’s another version of the panel – it can write to the external, receive it,
and restore previous now. still a bit fiddly to observe this but does work.
probably on the wrong track re: midi and preset routines but does what i set
out to do (so far). ‘send prog’ is now an idea for copying presets/data?Attachments:
You must be logged in to view attached files.October 28, 2017 at 6:05 pm #73315edit: woops, messed that up somehow (at least here),
i think that file has wrong methods triggered by wrong
buttons – try this one instead:
(mods if you can delete the previous file; i can’t remove it)>quickest test is to toggle ‘recv’ and ‘restore’ pressing the
same ‘preset’ buttons each time: you see the data changing in
the preset windows that contain the settings of the faders.Attachments:
You must be logged in to view attached files.October 29, 2017 at 9:11 am #73326when collecting values with a table,
i noticed a difference in output when i do memB(getByte,n)
and tableX[n]: getByte produced the wrong values, whereas
table is correct. so what format will getByte produce? hex?
table[n] seems to give me the literal values.um, i suppose when i do concatenatation and then a memory block,
i’m producing a string?October 29, 2017 at 9:37 am #73327ok, never mind, figured out what it was: needed to getByte
from the labels. now transfers all four presets:
(see panel/send single method>orange ‘send’ button)(lol, not convinced any of this is necessary but whatever…
it’s practice)Attachments:
You must be logged in to view attached files.October 29, 2017 at 10:31 am #73329good job i uploaded because i scr***d up just after that,
and it wouldn’t load at all π (turns out i forgot to
rename function titles after copying – was able to fix it
in notepad > method name vs -duplicate- function title conflict?)
– last version wasn’t copying names, does now.there is now a virtual ‘external device’ receiving data.
need to sort this out properly now.Attachments:
You must be logged in to view attached files.October 29, 2017 at 11:39 am #73331Hey Human Fly,
I finally worked out how to split a 240 byte string (e.g. direct from uiTextLabel) into 4 segments.
mySplitString = function(mod,value,source) a=panel:getModulatorByName("stringtosplit"):getComponent():getProperty("uiLabelText") local st = mySplitStringIntoFourSegments(a,60) for i,v in ipairs(st) do console(String(i.."[".. v.."]")) panel:getComponent("string0"..i):setPropertyString("uiLabelText",v) end end --function ------------------------------------ function myTrim(s) -- trim leading/trailing whitespace return (s:gsub("^%s*(.-)%s*$", "%1")) end --function ----------------------------------- function mySplitStringIntoFourSegments(text, stringSize) local j=1 -- counts to 4 local s = {} for i=1,#text,stringSize do s[j] = myTrim(string.sub(text,i,stringSize*j)) j=j+1 end return s end --function -----------------------------------
π
With regard to that panel I posted, did you unmute loopBe1?
-
AuthorPosts
- The forum ‘Using Ctrlr’ is closed to new topics and replies.