Forum Replies Created
-
AuthorPosts
-
You’ll probably have to write an onValueChange method for the knobs that update the value of the pad. You’ll need some sort of check to make sure to don’t generate a feedback loop (ie when you change the value on the xy-pad it updates the knobs, but when the knob updates, it will try to update the xy-pad, which will then trigger ctrlr to update the knob, etc.
The Puppeteer
http://godlike.com.auhttps://sourceforge.net/p/ctrlrv4/code/HEAD/tree/nightly/Source/MIDI/CtrlrMidiMessage.cpp#l243
If you want to utilize this message in Ctrlr, you’ll need to check for it in a midiReceive method that triggered when the panel receives MIDI.
Be aware though that timer functions in Ctrlr are unlikely to be accurate, as the timer can get interrupted by other things on the panel (like changing modulator values).
Ctrlr should pass the midi Clock messages through through from the host to the device, if MIDI Thru is turned on in the MIDI configuration of the panel.
The Puppeteer
http://godlike.com.auMIDI Clock should be passed. There’s some functions like isMidiClock to identify these messages. BPM isn’t passed through MIDI though. This would have to be part of the host parameters, if it is passed at all.
The Puppeteer
http://godlike.com.auNo it’s not local. Everything is global by default. You need to use local before a variable if you want it defined locally. Not sure if you can make methods local.
The Puppeteer
http://godlike.com.auNovember 11, 2017 at 11:57 pm in reply to: Is it possible to prevent running the OnModulatorValueChange method? #73481I’m including this for info on another possible way to address this, though it’s a major restructure for most panels.
In the panel I’m working on, I’m limited to doing sysex dumps to modify the synth’s edit buffer. I need to restrict bandwidth or I’ll crash the synth.
I ended up setting up a button to put the panel in “control mode”, which just starts a timer.
Inside the timer loop I maintain a memoryblock, and the previous copy of the memoryblock (tables also work) with all the values of the sysex dump. Each time the callback is triggered, I scan all of the ctrlr modulators, comparing them to the value in the previous memoryblock. If the memoryblock has changed, I send out MIDI, and update the previous memoryblock, with the new one (ie I have 2 variables called midiBuffer and lastMididBuffer).
In the onChange method for each ctrlr modulator I update a flag called bufferChanged which I can use to see if something has changed, from within the timer loop. I change this back to false on each scan of the modulators, or I can switch it off if I need to do something such as load a patch into ctrlr, or manage sysex dumps.
Also I make sure that dumps can’t be requested while in the control mode, so you can do whatever you want with the modulators while not in control mode and nothing will be sent to the synth.
Importantly I scan the control mode button. If it gets turned off, it stops the timer.
It’s a very different way of controlling stuff, but affords a lot of control over panel changes and bandwidth.
Also, thankyou so much Goodweather for the method for tracking multiple timers. It’s a very elegant method for keeping track of multiple timers and I wouldn’t be able to have my panel working without a similar approach.
- This reply was modified 6 years, 5 months ago by Puppeteer.
The Puppeteer
http://godlike.com.auHuman Fly,
MidiNuffer contains the hex values for a dump from a Roland Jupiter 8. Just consider them specimen values though. I update this Midi Buffer from the panel and send the Buffer to the Jupiter to update the edit buffer.
The Puppeteer
http://godlike.com.auDo a search on archive.org for tangent-cats.com
The K2000 doesn’t really have an accessible way of programming outside of screen replication.
I am working on a PC3 and Forte editor though that works through a special editor interface.
The Puppeteer
http://godlike.com.auMaybe try to remove getComponent() from the second set of commands, as you’ve already wrapped that into the variable.
ie first line should be
tabs_Main_pt1:setVisible(true)
The Puppeteer
http://godlike.com.auThanks Goodweather, I’ll use that as a reference if I get stuck. Hopefully will get a bit more coding done this week.
The Puppeteer
http://godlike.com.auI think I fixed my main problem with timers. Rookie mistake, spelt the method name wrong 🙁
Still got to work out whey the MIDI input callbacks on some modules are throwing errors though.The Puppeteer
http://godlike.com.auThere’s a pop up menu example in one of Atom’s demo panel’s I think.
The Puppeteer
http://godlike.com.auThanks, I’ll have a look.
The controls each change 1 or 2 bytes in the array, and then each 200ms I send the array to the synth, so I don’t need to queue the changes. Basically I need to sample the panel state every 200ms.
Thinking about it I might just be able to read the values of all controls every 200ms and do that, just an adjustment to how I initialize the panel.
Having problems with getting any timer Callback running at the moment, even ones that worked previously. Might look at my ctrlr version.
The Puppeteer
http://godlike.com.auGoodweather, thanks for the code above.
I’m working on a similar method for my Jupiter 8 panel and just wanted to clarify something.
I basically want the panel controls to update a sysex buffer (that’s maintained in ctrlr). currently it’s an array, but I may change it to a memory block, but that’s not really relevant.
Regardless of which control is moved, I want to limit the rate at which the sysex buffer is sent to the synth so that I don’t crash the processor. So basically I want the buffer to collect all panel changes and send it every 200ms (but only if the buffer has changed since the last message was sent)
Can I set the callback (using timer:setCallback) from each control using the same callback ID or do I need to somehow set the callback from a different more global control (like a on off button) and just get the controls to update the buffer?
Using the panel live is easy, because you only move one control at a time, but if you are automating it, several controls might be moving.
I’m putting the sendMidiMessageNow command within the timerCallback method, with a similar structure to what you have above.
The Puppeteer
http://godlike.com.auGoodweather, if you need somewhere to host it long term (or even until the issue is resolved here), please let me know via PM. You could supply a link to the file similar to what I did with the PC3 panel.
The Puppeteer
http://godlike.com.auThe last line of my example does this
‘
panel:getComponent(“recProg”):setComponentText(currentProg)
‘The Puppeteer
http://godlike.com.auHopefully this helps.
This is the method I use in a panel I’m developing for the Kurzweil PC3/Artis/Forte
Symbols is an array initialized in my initializePanel method. (Borrowed from the Miniak Panel, as the PC3 uses the same symbol set)
symbols = { [0]=””,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,
“|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,
” “,”!”,”\””,”#”,”$”,”%”,”&”,”‘”,”(“,”)”,”*”,”+”,”,”,”-“,”.”,”/”,
“0”,”1″,”2″,”3″,”4″,”5″,”6″,”7″,”8″,”9″,”:”,”;”,”<","=",">“,”?”,
“@”,”A”,”B”,”C”,”D”,”E”,”F”,”G”,”H”,”I”,”J”,”K”,”L”,”M”,”N”,”O”,
“P”,”Q”,”R”,”S”,”T”,”U”,”V”,”W”,”X”,”Y”,”Z”,”[“,”\\”,”]”,”^”,”_”,
“`
“,”a”,”b”,”c”,”d”,”e”,”f”,”g”,”h”,”i”,”j”,”k”,”l”,”m”,”n”,”o”,
“p”,”q”,”r”,”s”,”t”,”u”,”v”,”w”,”x”,”y”,”z”,”{“,”|”,”}”,”~”,”|”}
symbols2 = { [0]=””,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,
“|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,”|”,
” “,”!”,”\””,”#”,”$”,”%”,”&”,”\'”,”(“,”)”,”*”,”+”,”,”,”-“,”.”,”/”,
“0”,”1″,”2″,”3″,”4″,”5″,”6″,”7″,”8″,”9″,”:”,”;”,”<","=",">“,”?”,
“@”,”A”,”B”,”C”,”D”,”E”,”F”,”G”,”H”,”I”,”J”,”K”,”L”,”M”,”N”,”O”,
“P”,”Q”,”R”,”S”,”T”,”U”,”V”,”W”,”X”,”Y”,”Z”,”[“,”\\”,”]”,”^”,”_”,
“`”,”a”,”b”,”c”,”d”,”e”,”f”,”g”,”h”,”i”,”j”,”k”,”l”,”m”,”n”,”o”,
“p”,”q”,”r”,”s”,”t”,”u”,”v”,”w”,”x”,”y”,”z”,”{“,”|”,”}”,”~”,”|”}Data is the SYSEX dump assigned in the MIDI Receive method
data = midi:getData()
To generate the Program name I do this
local a={} for i=0,30 do -- this collects first 31 bytes and puts them into array a. This should include the program name. a=data:getByte(i) end –for
Then later.
j=11 while a[j] ~= 0x00 do name = name..symbols[a[j]] j=j+1 end --while prgName[receivedProgramNum]=": "..name -- update Program Received currentProg = string.format(nPrg) panel:getComponent("recProg"):setComponentText(currentProg)
I need the while statement because on the PC3 the program name is variable length and delimited by 0x00. If you have a fixed length program name you could make the while statement while a[j] < 20 (for example)
- This reply was modified 6 years, 8 months ago by Puppeteer.
- This reply was modified 6 years, 8 months ago by Puppeteer.
The Puppeteer
http://godlike.com.auI think you can, but you normally don’t. Do a search on the forum for this, because I think the modulator number is assigned by Ctrlr and may be unreliable. You can do something though like give a variable the Ctrlr name lookup.
This is what Atom does in the example modules, so you just define all the modulators on panel startup, and then refer to them as a variable during programming. You could use the variable name as something related to the MIDI CC Numbers, which would be the easiest way to accomplish this.
The Puppeteer
http://godlike.com.auI did this in LUA on a PC3 for outgoing messages, but the messages there are far more complex. Due to the vast number of parameters the control messages are 8 MIDI CC’s long.
I keep track of the last message and do a comparison. If certain elements change, then I send a whole new message, otherwise I send just the running status (ie the short version of the message). I need to do this due to bandwidth, and it’s in line with running messages in the MIDI spec.
To read them in (and this isn’t required on the PC3) I’d either drop them into an array based on the MIDI message, or have a series of IF THEN statements to work out which control should change, and then set the value of the Ctrlr control based on the valaue part of the NRPN. You’d need to make an assumption that unless you receive a new destination parameter that all messages are to change the currently selected control.
Pseudocode would go something like this (I’m not on a computer with Ctrlr or Lua at the moment so can’t do the actual coding)
Assume you read the incoming MIDI and for MIDI CC messages you put Byte 2 into midiCcNum and Byte 3 into midiCcVal
ie IF midiCcNum = 99 THEN
parameterNumber1 = midiCcVal
ELSEIF midiCcNum = 98 THEN
parameterNumber2 = midiCcVal
ELSEIF midiCcNum = 6 THEN
parameterNumber3 = midiCcVal
ELSIF midiCcNum = 38 THEN
ctrlrParamVal = midiCcValctrlrParamName = some function of parameterNumber1, parameterNumber2, parameterNumber3
The set ctrlrParamName.ctrlrParamVal
By default all variables are global in LUA, so just assign the messages to a new variable and it will be accessible to new methods.
- This reply was modified 6 years, 9 months ago by Puppeteer.
The Puppeteer
http://godlike.com.auEasiest way to start is make a control and in the panel on the right, add a method to onValueChange
Open that method and start coding.
For receiving SYSEX you’ll need a method that is called on receiving data. All the data checks and launching other methods will need to come from this receive method.
The Puppeteer
http://godlike.com.auThe issue here is Windows and more specifically how most MIDI drivers are programmed. Most Windows MIDI drivers aren’t able to be accessed by multiple applications at the same time.
Ctrlr has its own binding for the MIDI interface, so you’ll need to disable it within Sonar in order to use it with Ctrlr. The Ctrlr VSTi, will accept the incoming MIDI notes etc, and pass it through to the MIDI interface, acting like an external instrument.
The Puppeteer
http://godlike.com.au -
AuthorPosts