computerchemist

Forum Replies Created

Viewing 20 posts - 1 through 20 (of 31 total)
  • Author
    Posts
  • in reply to: MIDI Out LED #118758
    computerchemist
    Participant
    • Topics: 2
    • Replies: 31
    • Total: 33

    Maybe the Juce MidiBuffer Class can be helpful:

    Yes, I found that some time back but I’m not sure how it is exposed through Ctrlr. Have you got any worked Ctrlr examples to look at? My suspicion is that atom probably needs to do some C++ binding magic.

    in reply to: MIDI Out LED #118755
    computerchemist
    Participant
    • Topics: 2
    • Replies: 31
    • Total: 33

    It’s all cool, dude! Both methods have their use. In fact, I’m minded now to try mixing both approaches by making a bar on my giant floater.. I can’t split the sysex, but if I know for example after the size calculation it will take exactly 2000ms to send, I could divide the total time number by 4 and fire the timer every (2000/4)=500ms to say 0%.. 25%… 50%.. 75%.. done – once I have done that “magic number’ calculation the rest is easy. Just the bar – not the midi! I still wish there was a way to actually interrogate the midi out buffer directly, but I think these are all good solutions 🙂

    in reply to: MIDI Out LED #118748
    computerchemist
    Participant
    • Topics: 2
    • Replies: 31
    • Total: 33

    No, like I said above, I think there are two different use cases here – your one where you have little tiny packets you can break up, one at a time – in which case yes, you’d put the send in the timer function.
    My use case is completely different – I have one single big packet that I can’t split. So putting it in the timer wouldn’t accomplish anything – I can’t split it, so I can’t do the bar thing, or fire off the packets one at a time to the timer.
    In my code fragment above, encodesysex is the bad boy that puts together all the controllers into one sysex string – the Poly800 doesn’t understand CC’s, so it can only take one big sysex load.
    My problem was this – sendMidiMessageNow is ASYNCHRONOUS. So putting one giant packet send in the timer would be meaningless, as it would just send it and return instantaneously, then spend 2-3 seconds doing the upload of that giant packet. BUT – and this was the breakthrough moment – if I can accurately calculate the exact time it takes to send that giant packet, I can tell the timer EXACTLY how long to make the LED red. So the timer callback, as above, is purely the place where it makes the LED black at the end of the 2-3 second send. Does that make sense now? There are two different use cases.
    Yours works for split packets – not for giant floaters 😀
    To prevent any more confusion, here is the use case for big packets in full:

    function sendSysex()
    
    -- This stops index issues during panel bootup
    	if panel:getRestoreState() or panel:getBootstrapState() then
    		return;
    	end
    
        local mysysexData, my_c0, programChange, tempProg, j, currMidi, s, totwait;
    
    	if timer:isRegistered(40) == false then
    	    -- console ("timer40 not registered, do it now");
    		timer:setCallback(40, timer40Callback);
    	end
    
    	if timer:isTimerRunning(40) then
    		-- console ("timer40 already running, stop it");
    		timer:stopTimer(40);
    	end
    
    -- update sysex and add crc
        mysysexData=MemoryBlock();
    	
        mysysexData=encodeSysex();  -- create the full sysex dump
    
        s = mysysexData:getSize();
    
        totwait = tonumber( ( s * 0.32 ) + 5 ); -- 5ms for the global delay, totwait in ms
    
        -- console("start timer40...");
        panel:getModulatorByName("sendDumpButton"):getComponent():setProperty ("uiButtonTextColourOff","FFFF4545",true); -- make it red
        timer:startTimer (40, totwait); 
    
        panel:sendMidiMessageNow(CtrlrMidiMessage(mysysexData:toHexString(1)));
    
    end
    
    function timer40Callback()
        panel:getModulatorByName("sendDumpButton"):getComponent():setProperty ("uiButtonTextColourOff","FF454545",true); -- back to black
    	timer:stopTimer(40);
        -- console("stop timer40");
    end
    
    in reply to: MIDI Out LED #118742
    computerchemist
    Participant
    • Topics: 2
    • Replies: 31
    • Total: 33

    c takes a time to initialise, but I get what it’s doing – like you said earlier, it’s not answering the original question but it is a really neat way of doing a progress bar.
    But my problem isn’t sending lots of little packets, the Poly800 expects a giant floater of a packet in one go – depending upon which version it’s anywhere from 3273 bytes to 5383 bytes – in one single go. This actually takes over a second to upload, and during that time I’ve basically got to try and let the user know it’s happening. But becuase it could be big or small, it can’t be a fixed number.
    But I just tried this and it worked:

        mysysexData=MemoryBlock();
         mysysexData=encodeSysex();
         s = mysysexData:getSize();
    
        totwait = tonumber( ( s * 0.32 ) + 5 );
    
        -- console("start timer40...");
        panel:getModulatorByName("sendDumpButton"):getComponent():setProperty ("uiButtonTextColourOff","FFFF4545",true); -- set to red
        timer:startTimer (40, totwait); 
    
        panel:sendMidiMessageNow(CtrlrMidiMessage(mysysexData:toHexString(1))); -- go send it
    

    My callback basically stops the timer and sets the text back to black, but it’s bang on timing now. The trick was that “magic number’ and if you multiply the size of your sysex by 0.32 and add the current mididelay time onto it (in my case 5ms) it’s only bang on perfect 🙂

    So hoping this might help someone else out – two ways actually, your very nice bar progress for split packets or a precise LED on time for very big packets.

    in reply to: MIDI Out LED #118740
    computerchemist
    Participant
    • Topics: 2
    • Replies: 31
    • Total: 33

    Thanks for taking the time to do that – I’ll try it later.

    in reply to: MIDI Out LED #118735
    computerchemist
    Participant
    • Topics: 2
    • Replies: 31
    • Total: 33

    What I meant was that tu_rate doesn’t seem to be referenced after that, so I guess it was added in but never implemented?

    What I mean by the asynchronous is if you do something like:

    console("start")
    sendMidiMessageNow (stuff)
    console("end")

    then even if “stuff” is huge and would take several seconds to transfer, you’ll see “start” “end” immediately in the console. So you can’t just add some logic after the sendMidiMessageNow to turn off the led. That’s what I meant by asynchronous; it’s a “fire and forget” sort of operation that doesn’t stop your main program loop dead while it sends stuff.

    I think it sounds like the only way is to figure out how to calculate milliseconds given size of buffer to transfer and current delay settings. So it’ll be something like
    milliseconds_to_wait= (mysysexData:getSize() * magic_number )+ panelMidiGlobalDelay
    where magic_number will be the time in milliseconds for 10 bits (1 start, 8 data, 1 stop) to travel at 31.25 kBaud – the magic MIDI number.
    What the heck is magic_number…. 1/31250baud = 0.000032 seconds for a bit, 10 bits would be times ten so 0.00032 seconds per byte = 0.32 milliseconds per byte, is that right? Anybody? 0.32 is the magic_number? 😀 I’ll try it later an report back. Think you might have just helped steer me here onto something, dnaldoog!

    in reply to: MIDI Out LED #118731
    computerchemist
    Participant
    • Topics: 2
    • Replies: 31
    • Total: 33

    Thanks for the replies dnaldoog.
    Yes, I’m using a timer currently as a “kludge” but that’s highly dependent on what the current MIDI delay settings are set to, so it’s not as straightforward as working out the size for the data packet you’re about to send, although maybe that’s a better way of handling it, even if it’s a kludge.
    I guess there must be some magic formula to use to calculate the milliseconds accurately, as 31.25kBaud is a given, the only other two variables would be the delay and the size of the packet. If I made a function that acted as a wrapper around sendMidiMessageNow to instantiate the timer having looked at the size of the packet about to be sent, that would be a sort of answer, right?
    I looked at that JD panel but tu_rate doesn’t seem to go anywhere or be used for anything, so guessing there’s no “right” answer for this, if we can’t check the current MIDI output buffer queue everything we do for MIDI out is an approximation.

    in reply to: Global Persistent Variables? #118325
    computerchemist
    Participant
    • Topics: 2
    • Replies: 31
    • Total: 33

    Big shout out to both of you super helpful guys 🙂
    I got it all working in the end with a mixture of both approaches.

    in reply to: Global Persistent Variables? #118311
    computerchemist
    Participant
    • Topics: 2
    • Replies: 31
    • Total: 33

    Sorry – it was for the Korg Poly-800. I think I’ve taken the wrong approach then completely – because of all the bit slicing and shifting I decode the sysex in one block (it doesn’t handle CC or individual patches) into a 64×99 array which I then map onto the controllers. A prog up/down just refreshes the controllers from the appropriate row in the array. When saving, I read the controllers in a loop and update the appropriate row in the array. The first element is the program and the second is the controller. So the complete program patch state is stored in a 3 dimensional array from when it leaves the sysex (file or dump) to when it need to go back to be sysex (file or dump).
    Hold up – I think I answered my own question. Why not store the sysex dump which is a MemoryBlock prior to writing, I could treat the save state as a thrid way of storing sysex. Duh. On it now… 😀

    in reply to: Global Persistent Variables? #118309
    computerchemist
    Participant
    • Topics: 2
    • Replies: 31
    • Total: 33

    That just crashes and burns trying to reference the array directly – it doesn’t crash while saving state, but it doesn’t seem to write the arrays to the state table either. So when reading back in, I’m just getting a nil array.

    in reply to: Global Persistent Variables? #118308
    computerchemist
    Participant
    • Topics: 2
    • Replies: 31
    • Total: 33

    Thanks for the pointers (again) 🙂 Yes, it will store the current sliders but I can only do bulk sysex dumps to this synth so I need to store all 64 patches locally, not just the displayed one. I’ve probably take the long road doing that with arrays but I’ll give it a go.

    in reply to: Global Persistent Variables? #118304
    computerchemist
    Participant
    • Topics: 2
    • Replies: 31
    • Total: 33

    I have a follow on query that’s still within this context (sort of) and I hope you can help with too.

    I have a 3 dimensional array (table?), ProgramPatch[][] where the first element is the program number, the second element is the patch number in the program. I effectively want to store this into the State Data too.
    In other languages I’d serialise the array into a string, or use a JSON library to do the same. I just can’t seem to figure out the best way with LUA. What’s the best way in CTRLR of storing the array and retrieving it?

    in reply to: Global Persistent Variables? #118299
    computerchemist
    Participant
    • Topics: 2
    • Replies: 31
    • Total: 33

    Thanks! That is exactly what I’ve been looking for (and could not find!) 🙂

    in reply to: Using CTRLR plug in #73091
    computerchemist
    Participant
    • Topics: 2
    • Replies: 31
    • Total: 33

    I can help on the first part of your problem, as I ran into exactly this today trying on CTRLR in Windows 10, Cubase 9.
    The solution to seeing the whole screen is to click on the menu option “Edit” then “Preferences”, in what you can see inside the windowed plugin on the bottom right.

    From there, scroll down to the bottom. You’re in a form window called “Settings”, not “Preferences” because, well, I dunno. Maybe no-one noticed that before.
    Where it says “Editor Bounds” change that from whatever it says (mine always starts up with 560 220 800 600 and I have no idea why) to 0 0 1024 768

    The numbers refer to the relative position of your editor inside the VST plugin window. Leave the first two as “0 0” – that will always be top left – and change the last two to suit your plugin. 1024 is the width and that may need to be a little bigger, 768 is the height. You will need to close the VST Ctrlr window and reopen to see the changes.

    Hope that helps a little?

    in reply to: Roland D-110 panel #72973
    computerchemist
    Participant
    • Topics: 2
    • Replies: 31
    • Total: 33

    Ok, stupid question time. What settings MIDI-wise do you have on your unit (controller, MIDI channel). No matter what I do I can’t get a peep out of either of mine. I went back to that old panel with the CRC checksum errors, and the same thing – except I can make “checksum error” on the LCD with that one 🙂 Are the MIDI channel controls that set input/output/controller operative in the code or am I missing something? My next step is to hook ctrlr up to midiOX and have a look at what it’s doing but I thought I’d ask first if it’s something silly I’m doing.

    Funnily enough, not only do I have two D-110s I also have a Kawai K1r. And that works beautifully with the ctrlr controller, so there’s definitely not a problem with my keyboard/midi interface/version of ctrlr etc.

    Please don’t tell me you have a Korg M3R too or this will get really freaky.

    edit: I personally would stick with the direction you’ve got. Once it’s all operational in its current point maybe then is the time to write version 2 with all your learned knowledge to date, but also with code optimisation, librarian, input settings from D110, changes to positions, etc.

    in reply to: Roland D-110 panel #72967
    computerchemist
    Participant
    • Topics: 2
    • Replies: 31
    • Total: 33

    That does actually make a lot of sense.

    I found the link to the article those pictures originally came from, it’s good background reading for discussion too, as it’s reviewing the operation of the program.
    http://www.muzines.co.uk/articles/steinberg-synthworks-d10-20-110-mt32/57

    I have also been looking around for more info on the standalone pg-10 controller, I found the operation manual and service manual, but I don’t know if its a full set of screen prompts. Its a (physical) vertical arrangement of 8 sliders below a more navigable menu system than the D110. All sceeens can be accessed directly from the keypad on the right. They are so expensive when they come up for sale, yet in essence what you have on that screen i think is pretty much like an expanded graphical view of the pg-10.

    I have yet to sit down and really go through your panel to date. I will make some time for that this week.

    in reply to: Roland D-110 panel #72922
    computerchemist
    Participant
    • Topics: 2
    • Replies: 31
    • Total: 33

    I just tried the link but it failed with “This shared file or folder link has been removed or is unavailable to you.”

    in reply to: Roland D-110 panel #72874
    computerchemist
    Participant
    • Topics: 2
    • Replies: 31
    • Total: 33

    (edit) 🙂

    in reply to: Roland D-110 panel #72837
    computerchemist
    Participant
    • Topics: 2
    • Replies: 31
    • Total: 33

    Could you post the non-exe panel or panelz version please? I’m very wary of anything that’s an executable these days. Good progress though Mr. Fly. We are all very proud of your efforts to date 🙂

    in reply to: Roland D-110 panel #71506
    computerchemist
    Participant
    • Topics: 2
    • Replies: 31
    • Total: 33

    Ahh, ok, just didn’t want you to lose everything now it’s come so far!! I’m mostly 64bit VST now, do I try the link you posted feb 26? I think it’s moved on a little from the one I have because you noticed the error in the z4 thingys, if that’s all that’s changed I can keep that in synch.

Viewing 20 posts - 1 through 20 (of 31 total)
Ctrlr