|
|
|
06-28-2016, 07:29 AM
|
#1
|
Human being with feelings
Join Date: Aug 2010
Location: Germany
Posts: 2,185
|
Setting FX parameter from audio thread
Hi Justin,
thanks for the answers on your Q&A site. This is a follow-up to this and this question.
I'm working on a VST/IPlug plug-in. My goal is to set an FX parameter via REAPER API as reaction to a MIDI event (e.g. a fader). The MIDI event "arrives" on an audio thread in the IPlug ProcessMidiMsg() function.
It's important that there's no noticeable latency between the fader movement and the change of the FX parameter. It should happen instantly. Therefore I was thinking about calling TrackFX_SetParamNormalized() right there in the audio thread. Which seemed to work when using PreventUIRefresh() but you say it's bad and unpredictable . I tried executing it in the main thread by deferring the call so it's executed in IReaperControlSurface::Run(). But I noticed a slight latency. The Run() method is "called 30x/sec or so" - so "only" once per 33 milliseconds ... which I thought explains the latency I felt.
Do you have any ideas? Does REAPER's built-in MIDI learn / MIDI link also defer to the main thread?
Thanks for your time
Benjamin
|
|
|
06-28-2016, 09:07 AM
|
#2
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,688
|
Quote:
Originally Posted by helgoboss
My goal is to set an FX parameter via REAPER API as reaction to a MIDI event (e.g. a fader). The MIDI event "arrives" on an audio thread in the IPlug ProcessMidiMsg() function.
|
I don't exactly see you point.
ReaMidiControl can set effect parameters according to Midi events, but not "via REAPER API", but via the VST API (or is this, what you mean ?) . I do use this happily for live playing.
MidiToReaControlPath can send Midi Events from a track into "the guts of Reaper", so that e.g. ReaScripts can catch them. I happily use this to control SWS LiveConfigs while live playing.
-Michael
Last edited by mschnell; 06-28-2016 at 01:43 PM.
|
|
|
06-29-2016, 09:37 AM
|
#3
|
Human being with feelings
Join Date: Aug 2010
Location: Germany
Posts: 2,185
|
Hi Michael,
sorry, my words were maybe a bit confusing I was talking about a plug-in which for example translates MIDI CC changes to FX parameter changes (similar to REAPER's MIDI learn but with additional functionality and done as plug-in). This plug-in already exists and works: ReaLearn
I was just doing research if I can improve performance by doing certain things in the audio thread (instead of main thread) - but looks like even REAPER's built-in MIDI learn uses the main thread (can anybody confirm that?). So maybe I shouldn't bother at all.
It's exactly the opposite of ReaControlMIDI (which translates FX parameter changes to MIDI CC changes).
I have also been using MIDIToReaControlPath for a long time now for similar scenarios like yours (controlling SWS LiveConfigs, preprocessing control MIDI messages for creating musically useful controller-to-parameter mappings) - and it worked pretty well in the end. But setup and workflow was a pain - I was often more busy with setup than with making music.
Cheers
Ben
|
|
|
06-29-2016, 01:23 PM
|
#4
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,688
|
Quote:
Originally Posted by helgoboss
It's exactly the opposite of ReaControlMIDI (which translates FX parameter changes to MIDI CC changes).
|
???
I do use ReaControlMIDI exactly in the way you describe you want to.
It is loaded in a track together with a VSTi. It receives midi CC messages ("Control change" is enabled and in one slot a controller is set to not- <none>). Now for the VSTi the appropriate "param"eter from the list is set to "Parameter Modulation / Midi Link" and linked to "ReaMidiCOntrol" -> the_appropriate_cc.
Now you an set the offset and scale (i.e. a linear function) the parameter is set by the CC ReaMidiControl receives.
If I need additional functionality I do JSFX plugins to modify the CC. Up till now this has been versatile enough.
-Michael
Last edited by mschnell; 06-29-2016 at 01:30 PM.
|
|
|
06-29-2016, 03:09 PM
|
#5
|
Human being with feelings
Join Date: Aug 2010
Location: Germany
Posts: 2,185
|
Oh okay, now I see what you mean. It's even easier than that! Since REAPER v5.11pre4 you don't need ReaControlMIDI anymore to achieve this. You can just choose the CC directly in the "Parameter Modulation / MIDI Link" dialog.
Parameter modulation is certainly a cool feature. If you are happy with it for controlling parameters, that's perfect. I'm not trying to convince people here to use something different, I just provide options.
But back to my original questions to the REAPER devs.
1. Can anybody confirm that REAPER's MIDI learn functionality schedules parameter changes on the main thread? (MIDI control event arrives on audio thread => FX parameter is adjusted in the next main loop cycle)
2. MIDI Link as well?
|
|
|
07-01-2016, 11:39 PM
|
#6
|
Human being with feelings
Join Date: Jun 2016
Location: London, UK
Posts: 51
|
Quote:
Originally Posted by helgoboss
1. Can anybody confirm that REAPER's MIDI learn functionality schedules parameter changes on the main thread? (MIDI control event arrives on audio thread => FX parameter is adjusted in the next main loop cycle)
2. MIDI Link as well?
|
Hi Benjamin,
I would like to echo your above questions.
Currently I am scheduling parameter changes in the audio thread. It would be good to hear from an expert how and where I should actually be doing this.
Kind regards,
Leigh
|
|
|
11-16-2021, 03:04 PM
|
#7
|
Human being with feelings
Join Date: Oct 2018
Posts: 39
|
Has anybody found the answer to this?
|
|
|
11-16-2021, 11:33 PM
|
#8
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,688
|
As mentioned above, ReaControlMIDI and ReaLearn obviously can do this.
I did a Juce VST doing this.
-Michael
|
|
|
11-17-2021, 06:56 AM
|
#9
|
Human being with feelings
Join Date: Oct 2018
Posts: 39
|
I know about parameter modulation / midi link. My question is about setting FX parameters from a vst without waiting for the IReaperControlSurface::Run() function in the main thread.
|
|
|
11-17-2021, 07:47 AM
|
#10
|
Human being with feelings
Join Date: Aug 2010
Location: Germany
Posts: 2,185
|
Quote:
Originally Posted by lexomir
I know about parameter modulation / midi link. My question is about setting FX parameters from a vst without waiting for the IReaperControlSurface::Run() function in the main thread.
|
Have a look here: https://www.askjf.com/index.php?q=5697s
TL;DR:
As Justin confirms once more in this thread, setting parameters directly from the audio thread is a no go. However, SetTimer() might give you less waiting time than waiting for Run().
|
|
|
11-17-2021, 08:17 AM
|
#11
|
Human being with feelings
Join Date: Oct 2018
Posts: 39
|
Ah, thanks. That will speed it up a bit.
Don't suppose we ever figured out if reaper's native midi learn stuff also pushes changes to the main thread?
|
|
|
11-17-2021, 10:35 AM
|
#12
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,688
|
Quote:
Originally Posted by lexomir
My question is about setting FX parameters from a vst
|
A VST can attach to the Reaper API by means of the VST "Client extemsions".
The recent Juce SDK provides this as well for VST2 as for VST3.
I have a running example that uses as well the Reaper API (which e.g. allows for defining parameters of VSTs, as ReaLearn proves), as the VST GUI embedding, Reaper can do,
See (e.g.) this thread -> https://forum.cockos.com/showthread....highlight=JUCE
-Michael
|
|
|
11-17-2021, 10:39 AM
|
#13
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,688
|
Quote:
Originally Posted by helgoboss
setting parameters directly from the audio thread is a no go.
|
I suppose this is true for VST2.
But with VST3 "sample accurate parameter modulation" I feel that it's necessary to do this in the audio thread to make sure the correct audio block is affected.
A Discussion in the Juce forum (-> https://forum.juce.com/t/notifying-h...-changes/48462 ) seems to show that the appropriate callback in Juce can come as well on the audio as on the GUI thread, and the user might need to query the thread type before doing certain actions. (Unfortunately Juce does not yet support sample accurate parameter modulation.)
-Michael
Last edited by mschnell; 11-17-2021 at 04:22 PM.
|
|
|
11-17-2021, 10:44 AM
|
#14
|
Human being with feelings
Join Date: Aug 2010
Location: Germany
Posts: 2,185
|
Quote:
Originally Posted by lexomir
Ah, thanks. That will speed it up a bit.
Don't suppose we ever figured out if reaper's native midi learn stuff also pushes changes to the main thread?
|
It seemingly does. Just native-MIDI-learn a parameter of your plug-in, set a break point in the "set parameter" function of it and invoke the learned control. The break point is hit in the main thread, at least here on Windows with my VST2 plug-in and a pretty standard REAPER config. I can see that one of the lowest stack frames is the Windows event loop.
|
|
|
11-17-2021, 10:49 AM
|
#15
|
Administrator
Join Date: Mar 2007
Location: NY
Posts: 15,750
|
Quote:
Originally Posted by lexomir
Don't suppose we ever figured out if reaper's native midi learn stuff also pushes changes to the main thread?
|
Yes, absolutely. UI interaction related activity, including FX parameter changes, happens from the main thread.
|
|
|
11-17-2021, 10:59 AM
|
#16
|
Human being with feelings
Join Date: Oct 2018
Posts: 39
|
To clarify, I'm talking about my vst controlling parameters for other external plugins on the chain (using functions like TrackFX_SetParamNormalized, etc). The VST3 "Sample accurate modulation" stuff is for processing changes of my vst's parameters only.
From the links helgaboss gave, it seems like this can only be done by deferring to the main thread.
I'm guessing that is how Realearn also does it.
|
|
|
11-17-2021, 11:02 AM
|
#17
|
Human being with feelings
Join Date: Aug 2010
Location: Germany
Posts: 2,185
|
Quote:
Originally Posted by mschnell
I suppose this is true for VST2.
|
I was talking about invoking REAPER API functions only (e.g. TrackFX_SetParam), not about invoking the "set parameter" function of the plug-in itself. I think "call me from main thread only" is a restriction that REAPER imposes on us, not the plug-in. I'm not sure which are the exact threading rules of the various plug-in standards but at least some of those standards very well allow parameter changes from any thread, including real-time threads. However, since we are developing *for REAPER* = for the *host* side of things, the answer to this question is not that relevant I would say. We must conform to rules that REAPER imposes on us.
Quote:
Originally Posted by mschnell
But with VST3 "sample accurate parameter modulation" I feel that it necessary to do this in the audio thread.
A Discussion in the Juce forum seems to show that the appropriate callback in Juce can come as well on the audio as on the GUI thread, and the user might need to query the thread type before doing certain actions.
-Michael
|
VST plug-ins must be ready to deal with "set parameter" invocations from multiple threads, that's true. In general, REAPER calls "set parameter" not just from the main thread. E.g. when you read automation, it calls "set parameter" on the "reaper.exe" thread (on Windows).
|
|
|
11-17-2021, 11:03 AM
|
#18
|
Human being with feelings
Join Date: Oct 2018
Posts: 39
|
Quote:
Originally Posted by schwa
Yes, absolutely. UI interaction related activity, including FX parameter changes, happens from the main thread.
|
Ok, but "midi link" isn't necessarily UI interaction, it responds to track midi events, not just controller input.
|
|
|
11-17-2021, 11:12 AM
|
#19
|
Human being with feelings
Join Date: Oct 2018
Posts: 39
|
Regardless, I was just curious how it works. I wasn't sure if Reaper's "Midi Link" posted changes to the other plugins in a way similar to how automation does it on the audio thread.
Thanks for the information!
|
|
|
11-17-2021, 11:15 AM
|
#20
|
Human being with feelings
Join Date: Aug 2010
Location: Germany
Posts: 2,185
|
Quote:
Originally Posted by lexomir
From the links helgaboss gave, it seems like this can only be done by deferring to the main thread.
I'm guessing that is how Realearn also does it.
|
Yes, that's how ReaLearn does it. Back in the C++ days, ReaLearn used a lock-free queue to do the interthread communication ( https://github.com/cameron314/concurrentqueue), now it uses a Rust channel to do the same, but you can use whatever synchronization primitive you like.
At the time I started this thread I was trying to come up with something very clever, calling TrackFX_SetParam() from a real-time thread (in particular the one that dispatched the incoming MIDI messages, in my case the audio driver thread). It sometimes worked, sometimes crashed ... undefined behavior. You don't want to do this
|
|
|
11-17-2021, 11:18 AM
|
#21
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,688
|
Quote:
Originally Posted by lexomir
The VST3 "Sample accurate modulation" stuff is for processing changes of my vst's parameters only.
From the links helgaboss gave, it seems like this can only be done by deferring to the main thread.
I'm guessing that is how Realearn also does it.
|
In the Juce Forum I learned that in theory with VST3 sample accurate parameter modulation and transferring Midi CCs is essentially the same activity (obviously on the Track Audio thread). I don't know if/how Reaper supports sample accurate parameter modulation with VST3 (it obviously supports Midi CC transfer).
As Juce does not support sample accurate parameter modulation yet I can't test this with a decent effort.
BTW.: if you want to control 3rd party VSTs, I understand that it's not viable with VST2 and regarding VST3, not too many will decently support sample accurate parameter modulation and hence you will not be able to improve anything, in these cases.
-Michael
Last edited by mschnell; 11-17-2021 at 11:50 AM.
|
|
|
11-17-2021, 11:24 AM
|
#22
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,688
|
Quote:
Originally Posted by helgoboss
In general, REAPER calls "set parameter" not just from the main thread. E.g. when you read automation, it calls "set parameter" on the "reaper.exe" thread (on Windows).
|
It would be rather silly if the setParameter VST API would be (necessary to be) called on the GUI thread when we do "Midi Link".
In fact "Midi Link" should be a trivial action in VST3, as seemingly VST3 receives Midi CCs as sample accurate Parameter Modulation.
-Michael
|
|
|
11-17-2021, 11:30 AM
|
#23
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,688
|
Quote:
Originally Posted by lexomir
Ok, but "midi link" isn't necessarily UI interaction, it responds to track midi events, not just controller input.
|
The source of Midi Link always is Midi on the track (and hence in the track's realtime audio thread).
Very different for "Learn" which in fact does not receive Midi at all but messages on the Reaper Control Path, (which is on the GUI thread and also holds e.g. messages generated by OSC receive). Such "Midi type" messages might or might not be generated from actual Midi events (e.g. by setting the "control" checkbox in the Mid driver setting). They also can be generated via the Reaper API (also on the GUI thread).
-Michael
Last edited by mschnell; 11-17-2021 at 11:54 AM.
|
|
|
11-17-2021, 11:41 AM
|
#24
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,688
|
Quote:
Originally Posted by lexomir
IMy question is about setting FX parameters from a vst without waiting for the IReaperControlSurface::Run() function in the main thread.
|
The problem you seemingly want to solve is not just "waiting" (for activity of another thread).
In fact the Audio / Midi activity is done in "virtual Realtime": Reaper takes care that the audio blocks (and Midi events associated to them) always are "in sync" (regarding the block sequence number, not "wallclock" time), with each other for any calculation.
Anything happening in the Gui thread (or inter-thread communication at the same wallclock tick) can be off by multiple sample blocks. Hence only "sample accurate parameter modulation provides decent timing.
I suppose Reaper performs nice tricks to feed a plugin with envelope automation values together with the correct audio block; so this is off by max a whole audio block.
-Michael
Last edited by mschnell; 11-17-2021 at 11:55 AM.
|
|
|
11-17-2021, 11:45 AM
|
#25
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,688
|
Quote:
Originally Posted by helgoboss
but you can use whatever synchronization primitive you like.
|
Juce provides such a Queue as well. I use this when accessing the Reaper API in the GUI thread in the callback that receives Midi (obviously ín the Audio thread).
-Michael
|
|
|
11-17-2021, 11:46 AM
|
#26
|
Human being with feelings
Join Date: Oct 2018
Posts: 39
|
The source of "Midi Link" is from the audio thread, but updating the parameters is pushed to the GUI / Main thread.
I guess if a plugin supports audio rate modulation, you should try to use that particular vst's built in midi mapping functionality if possible.
|
|
|
11-17-2021, 11:49 AM
|
#27
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,688
|
I don't exactly know the VST2 or VST3 API specs, but I understand that it allows to do the set parameter stuff on any thread. Hence it might be not a good idea that Reaper always defers "Midi Link" to the GUI thread.
-Michael
|
|
|
Thread Tools |
|
Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -7. The time now is 06:17 PM.
|