Old 06-28-2016, 07:29 AM   #1
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 2,185
Default 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
helgoboss is online now   Reply With Quote
Old 06-28-2016, 09:07 AM   #2
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,688
Default

Quote:
Originally Posted by helgoboss View Post
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.
mschnell is offline   Reply With Quote
Old 06-29-2016, 09:37 AM   #3
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 2,185
Default

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
helgoboss is online now   Reply With Quote
Old 06-29-2016, 01:23 PM   #4
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,688
Default

Quote:
Originally Posted by helgoboss View Post
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.
mschnell is offline   Reply With Quote
Old 06-29-2016, 03:09 PM   #5
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 2,185
Default

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?
helgoboss is online now   Reply With Quote
Old 07-01-2016, 11:39 PM   #6
leighhunt
Human being with feelings
 
Join Date: Jun 2016
Location: London, UK
Posts: 51
Default

Quote:
Originally Posted by helgoboss View Post
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
leighhunt is offline   Reply With Quote
Old 11-16-2021, 03:04 PM   #7
lexomir
Human being with feelings
 
lexomir's Avatar
 
Join Date: Oct 2018
Posts: 39
Default

Has anybody found the answer to this?
lexomir is offline   Reply With Quote
Old 11-16-2021, 11:33 PM   #8
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,688
Default

As mentioned above, ReaControlMIDI and ReaLearn obviously can do this.

I did a Juce VST doing this.

-Michael
mschnell is offline   Reply With Quote
Old 11-17-2021, 06:56 AM   #9
lexomir
Human being with feelings
 
lexomir's Avatar
 
Join Date: Oct 2018
Posts: 39
Default

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.
lexomir is offline   Reply With Quote
Old 11-17-2021, 07:47 AM   #10
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 2,185
Default

Quote:
Originally Posted by lexomir View Post
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().
helgoboss is online now   Reply With Quote
Old 11-17-2021, 08:17 AM   #11
lexomir
Human being with feelings
 
lexomir's Avatar
 
Join Date: Oct 2018
Posts: 39
Default

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?
lexomir is offline   Reply With Quote
Old 11-17-2021, 10:35 AM   #12
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,688
Default

Quote:
Originally Posted by lexomir View Post
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
mschnell is offline   Reply With Quote
Old 11-17-2021, 10:39 AM   #13
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,688
Default

Quote:
Originally Posted by helgoboss View Post
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.
mschnell is offline   Reply With Quote
Old 11-17-2021, 10:44 AM   #14
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 2,185
Default

Quote:
Originally Posted by lexomir View Post
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.
helgoboss is online now   Reply With Quote
Old 11-17-2021, 10:49 AM   #15
schwa
Administrator
 
schwa's Avatar
 
Join Date: Mar 2007
Location: NY
Posts: 15,750
Default

Quote:
Originally Posted by lexomir View Post
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.
schwa is offline   Reply With Quote
Old 11-17-2021, 10:59 AM   #16
lexomir
Human being with feelings
 
lexomir's Avatar
 
Join Date: Oct 2018
Posts: 39
Default

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.
lexomir is offline   Reply With Quote
Old 11-17-2021, 11:02 AM   #17
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 2,185
Default

Quote:
Originally Posted by mschnell View Post
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 View Post
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).
helgoboss is online now   Reply With Quote
Old 11-17-2021, 11:03 AM   #18
lexomir
Human being with feelings
 
lexomir's Avatar
 
Join Date: Oct 2018
Posts: 39
Default

Quote:
Originally Posted by schwa View Post
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.
lexomir is offline   Reply With Quote
Old 11-17-2021, 11:12 AM   #19
lexomir
Human being with feelings
 
lexomir's Avatar
 
Join Date: Oct 2018
Posts: 39
Default

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!
lexomir is offline   Reply With Quote
Old 11-17-2021, 11:15 AM   #20
helgoboss
Human being with feelings
 
helgoboss's Avatar
 
Join Date: Aug 2010
Location: Germany
Posts: 2,185
Default

Quote:
Originally Posted by lexomir View Post
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
helgoboss is online now   Reply With Quote
Old 11-17-2021, 11:18 AM   #21
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,688
Default

Quote:
Originally Posted by lexomir View Post
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.
mschnell is offline   Reply With Quote
Old 11-17-2021, 11:24 AM   #22
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,688
Default

Quote:
Originally Posted by helgoboss View Post
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
mschnell is offline   Reply With Quote
Old 11-17-2021, 11:30 AM   #23
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,688
Default

Quote:
Originally Posted by lexomir View Post
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.
mschnell is offline   Reply With Quote
Old 11-17-2021, 11:41 AM   #24
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,688
Default

Quote:
Originally Posted by lexomir View Post
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.
mschnell is offline   Reply With Quote
Old 11-17-2021, 11:45 AM   #25
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,688
Default

Quote:
Originally Posted by helgoboss View Post
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
mschnell is offline   Reply With Quote
Old 11-17-2021, 11:46 AM   #26
lexomir
Human being with feelings
 
lexomir's Avatar
 
Join Date: Oct 2018
Posts: 39
Default

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.
lexomir is offline   Reply With Quote
Old 11-17-2021, 11:49 AM   #27
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,688
Default

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
mschnell is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 06:17 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.