Confused by patch request when combining sysex and virtual controls

I’m a little confused by setting up the patch request when you’ve got a combination of SysEx and Virtual controls. In the past I successfully set everything up in the JSON file when it was pure SysEx, but now that I’ve added a lot of LUA scripting with more virtual controls I’m unclear what to put where.

I set up the requests response headers in JSON, but I left out the rules nodes, and then I tried:

function patch.onResponse (device, responseId, sysexBlock)
	parameterMap.set (1, PT_SYSEX, 108, sysexBlock:peek(25))
end

…but the control isn’t changing. I guess the blank rules node in JSON is overriding the LUA code? Am I supposed to either use JSON or LUA, or both?

OK, I think it’s functioning now. I think each control wasn’t assigned to the right device.

Still scratching my head a bit with this. I’m trying to use the web app to add the rule mappings for the patch requests, but the virtual controls aren’t being updated. I’m not sure if the virtual controls must be updated in LUA or if I’m entering the rules incorrectly in the web app.

I’ve entered the requests and responses, and they seem to be correct:

I’ve also entered some rules, some which are for sysex controls and some which are for virtual controls.

I couldn’t find documentation to confirm that msg: "virtual", is valid, but the green checkmark in the web app suggests it is.

Despite the green check mark, I always get “no mappings found” under the control, and the responses lack complete results (notice every value is “00h”, but this is not true). Am I right to assume this part of the web app is incomplete? I’m not clear on what the marked bits with the green circles really mean.

Looking in the log it confirms what I see on my E1 screen. The controls with sysex messages are being updated, but the virtual ones are being ignored.

Trying to understand the best way to do this. Am I doing this wrong in the web app? Or should everything be done in LUA using patch.onResponse?

I’ve got part of the way there, but with the way I’ve set it up it’s overloading the MIDI buffer on my synth and freezing it. This wasn’t happening before virtual parameters.

First I put only the patch response headers into JSON:

Then I moved the requests over to LUA:

function patch.onRequest(device)
    local chan = parameterMap.get (1, PT_VIRTUAL, 311)
    local requestVoiceDump = {0x43,chan+32,0x7e,0x4c,0x4d,0x20,0x20,0x38,0x39,0x37,0x36,0x41,0x45}
        midi.sendSysex (PORT_1, requestVoiceDump)
    local requestSystemDump = {0x43,chan+32,0x7e,0x4c,0x4d,0x20,0x20,0x38,0x39,0x37,0x36,0x53,0x30}
        midi.sendSysex (PORT_1, requestSystemDump)
    local requestEffectsDump = {0x43,chan+32,0x7e,0x4c,0x4d,0x20,0x20,0x38,0x39,0x37,0x36,0x53,0x32}
        midi.sendSysex (PORT_1, requestEffectsDump)
end

function patch.onResponse (device, responseId, sysexBlock)
    local blockLength = sysexBlock:getLength()
    print ("Received sysex message " .. blockLength .. " bytes long.")
    if blockLength == 41 then
        parseACED (sysexBlock)
    elseif blockLength == 101 then
        parseVCED (sysexBlock)
    elseif blockLength == 45 then
        parseSYS (sysexBlock)
    elseif blockLength == 73 then
        parseFX (sysexBlock)
    end
end

Then I put in the rules in like so:

parameterMap.set (1, PT_SYSEX  , 99, sysexBlock:peek(7))  -- Op4 AR (Attack Rate)
parameterMap.set (1, PT_SYSEX  , 1,  sysexBlock:peek(8))  -- Op4 D1R (Decay 1 Rate)
parameterMap.set (1, PT_SYSEX  , 2,  sysexBlock:peek(9))  -- Op4 D2R (Decay 1 Rate)
parameterMap.set (1, PT_SYSEX  , 3,  sysexBlock:peek(10)) -- Op4 RR (Release Rate)
parameterMap.set (1, PT_VIRTUAL, 4,  sysexBlock:peek(11)) -- Op4 D1L (Decay 1 Level)

It looks like each parameterMap.set() function sends out a midi message, so it’s too much MIDI traffic for the synth to handle. When the mapping rules are purely in JSON they don’t do that. So still stuck with my original problem. How do I sync the virtual controls with the synth’s memory?

OK, I think I found a working solution to this. Virtual controls have to be handled in LUA, whereas the mapping of non-virtual controls should be done by the rules in JSON.

I was stuck in LUA with preventing the midi messages from being transmitted during a patch request, because during a patch request I just wanted to update the virtual controls to match the parameters on the synth. Every control sending out midi messages during a patch request actually froze my synth. Unfortunately, the function that transmits midi is tied to the virtual control so it can change single parameters, so I needed to find a method of suppressing the midi message when the patch request button is pressed. So here’s the important code from my preset to do that:

patchRequestSent = false

-- when parameters are changed by controls
function parameterMap.onChange (valueObjects, origin, midiValue)
    if (origin ~= INTERNAL) then return end -- Process only if user changes things (can be INTERNAL, MIDI or LUA)
    patchRequestSent = false
end

-- patch request, response and parse
function parseVCED (sysexBlock)
    parameterMap.set (1, PT_VIRTUAL, 50, sysexBlock:peek(57)) -- Op1 CRS (Coarse Frequency)
end

function patch.onRequest(device)
    patchRequestSent = true -- flag patch request
    local chan = parameterMap.get (1, PT_VIRTUAL, 311)
    local requestVoiceDump = {0x43,chan+32,0x7e,0x4c,0x4d,0x20,0x20,0x38,0x39,0x37,0x36,0x41,0x45}
        midi.sendSysex (PORT_1, requestVoiceDump)
end

function patch.onResponse (device, responseId, sysexBlock)
    local blockLength = sysexBlock:getLength()
    print ("patch.onResponse: Received sysex message " .. blockLength .. " bytes long.")
    if blockLength == 41 then
        parseACED (sysexBlock)
    elseif blockLength == 101 then
        parseVCED (sysexBlock)
    end
end

-- function hooked into control
function sendCoarseMidiMessage (opNum, fixedMidiVal, coarseMidiVal, fineMidiVal)
    if patchRequestSent == false then -- suppress midi during patch request
        local crs_message = {0x43,chan+16,0x12,paramNums[2],coarseMidiVal}
             midi.sendSysex (PORT_1, crs_message)
    end
end
2 Likes

congrats on coming up with a way to have JSON and LUA functionality playing nicely together.

1 Like