Roland multi-byte sysex #140
-
I've started putting together my first panel. It's for a Roland Jupiter Xm, so it's mostly sysex. Everything works following the tutorial, with one exception. The problem is with sysex messages with 4-byte values that use the r1 r2 r3 r4 formula (e.g. f0 41 10 00 00 00 65 12 02 10 00 4f r1 r2 r3 r4 z8 f7). They only work in one direction. I can send values to the Xm by moving a slider on the Ctrlr panel, but when I change the parameter with the knob on the Xm, the modulatorValue just jumps to zero. The midi monitor shows that the correct message is coming in from the Xm, and single-byte values (xx) and 2-byte values (ms ls) work in both directions, so I am wondering if there is a bug. I assume I could write a lua routine to process the incoming messages, if I learned some lua, but it would be great if the simple method would work. Does anyone know what is going wrong? PS I'm using Ctrlr 5.3.201 on Windows 10 (20H2). |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 7 replies
-
Could you tell me which parameter you are talking about? One parameter that uses 4 bytes is the "initial pattern number" (page 15 of the midi implementation) to reach values of 1-65536. I'm afraid you need Lua to do that. There is a topic started by Baus that's about reaching higher values than 127 with one modulator. Although the values might be different for the Roland-XM, need to see some incoming midi data to see what's happening, the process is almost the same when it comes to writing a lua script. |
Beta Was this translation helpful? Give feedback.
-
I think you are right! MS LS and ms ls work, but r1 - r4 don't. You need lua. It's a bit complex because it seems the panel still updates the component (uiSlider) to 0 after incoming MIDI so I used a timer to update the uiSlider with the incoming value few milliseconds later. The code for updating the uiSlider midiReceived = function(--[[ CtrlrMidiMessage --]] midi) local s = midi:getSize() if s == 18 then sum=0 -- initialize variable panel:setPropertyInt("panelMidiPauseOut", 1) -- don't let MIDI be sent if midi:getData():getByte(6) == 0x65 then -- this byte can indicate which modulator to change local r1 = midi:getData():getByte(12) local r2 = midi:getData():getByte(13) local r3 = midi:getData():getByte(14) local r4 = midi:getData():getByte(15) local lsb = assemble4bitNibble(r3, r4) -- convert 4 bit nibbles to number local msb = assemble4bitNibble(r1, r2) * 256 --local msb = bit.lshift(assemble4bitNibble(r1, r2),8) -- equivalent to the code above sum = (msb + lsb) -- global variable passed to timer timer:setCallback (1,timerCallback) -- don't update the uiSlider here - do it in this timer timer:startTimer(1,125) -- less might be okay! end -- BYTE = 65h end end function assemble4bitNibble(a, b) -- convert two 4 bit nibbles to a single integer local m = bit.lshift(a, 4) return m + b end --f If multiple uiSliders need this code then you need to check for a unique byte in the incoming message and update the correct uiSlider accordingly. In this example arbitrarily I look for byte 6 and check whether the value is 65h. And you'd probably wrap this all in a function if there are multiple modulators (e.g. uiSliders) to update. and the timer code : function timerCallback(timerId) if timerId == 1 then panel:getModulatorByName("mySlider"):setModulatorValue(sum,false,true,false) panel:setPropertyInt("panelMidiPauseOut", 0) -- let MIDI be sent timer:stopTimer(timerId) end end --end function Using Ctrlr 5.3.201 See attached panel Roland Jupiter XM_140_0_GitHub_2021-01-27_19-21.zip P.SYou can probably delete : panel:setPropertyInt("panelMidiPauseOut", 1) -- don't let MIDI be sent panel:setPropertyInt("panelMidiPauseOut", 0) -- let MIDI be sent and set ; panel:getModulatorByName("mySlider"):setModulatorValue(sum,false,false,false) |
Beta Was this translation helpful? Give feedback.
-
I had a look at the ctrlr source, and it seems that the code to process r1-r4 in incoming sysex messages has never been implemented. It's easy to see what's missing by looking up where the other tokens appear. The function indirectReverseOperation in ctrlr/Source/Core/CtrlrUtilities.cpp has a chain of if-statements that set the appropriate bits in the return variable each time a known token is encountered. Since the r1-r4 tokens are not known, no bits are set, and a value of zero is returned for any message that tries to use them. |
Beta Was this translation helpful? Give feedback.
Hi @ConditionalInstability
I think you are right! MS LS and ms ls work, but r1 - r4 don't.
You need lua. It's a bit complex because it seems the panel still updates the component (uiSlider) to 0 after incoming MIDI so I used a timer to update the uiSlider with the incoming value few milliseconds later.
The code for updating the uiSlider