Joining apple audio workgroup from non-juce thread spawned inside of Juce plugin?


I’m working on wrapping an audio library as a Juce plugin - a library which supports multicore audio processing, also on Mac OS.

For the spawned (posix) threads to join the apple audio workgroup, the library takes the “output device name” as input.

Is there a way in JUCE to get this name, when the app is a plugin, meaning there’s no AudioDeviceManager to fetch the AudioDeviceSetup from?

Alternatively, a way to get the “os_workgroup_t p_workgroup”, so as to join the workgroup directly, would be useful too.

I know the workgroup feature is a recent addition on the develop branch, but since this will potentially hold our plugin’s performance back on Mac OS it’d be great if we could add this support to it!

Ilias B.

I’ve been reading up on how close to making this possible Juce is from reading the develop branch commits on workgroups, and in the individual comments of the threads found on the forum.

It seems that:

1: It’s possible to start a Juce::thread, in an AU plugin, and have it join a workgroup.

2: It’s NOT possible through Juce to get the workgroup reference so that a posix thread can join it, AU or not.

3: It is ALSO not possible to join a workgroup, from a non-AU plugin.

(FR: Thread-Priority vs Efficiency/Performance Cores - #62 by anthony-nicholls)
(Os_workgroup_join consistently returns EINVAL - Can't join Audio Workgroup - #10 by ChrisASpatial)

It would be fantastic if there was a - static(?) - method, querying a thread for the workgroup it is in, from within the audio processing callback. Then that information can be used to join other threads to the same workgroup. This would allow also VST3 plugins to support workgroups, not only AU. I haven’t found anything in the Apple documentation to suggest this is possible, but hopefully I’m missing something?

Meanwhile, a feature request for Juce: at least from within an AU plugin, can such a method be implemented, to give workgroup information without starting a thread, so that it can be passed into 3rd-party libraries which support apple workgroups?
I see in AudioProcessor there is:

/** This is called by the host when the thread workgroup context has changed.

    This will only be called on the audio thread, so you can join the audio workgroup
    in your implementation of this function.

    You can use this workgroup id to synchronise any real-time threads you have.
    Note: This is currently only called on Apple devices.
virtual void audioWorkgroupContextChanged ([[maybe_unused]] const AudioWorkgroup& workgroup) {}

Anything along those lines, that can be queried as well (exposing the platform specific os_workgroup_t p_workgroup), and isn’t only a callback, would be very useful!

I don’t believe standard posix threads can or should join a workgroup, the thread should first be upgraded to “realtime”, and to be upgraded it first needs to use a different API to the standard posix one.

I think to do this will likely require extensions to the existing formats. I’m not sure getting the thread during the process callback via a static method is the best option. You probably want everything to join it, then do the processing and be allowed to let plugins know when to leave the workgroup and join a new one too.

Apples implementation is a callback, we’re just passing that callback on. It’s quite rare for JUCE to expose platform specific types, we normally want things to be platform agnostic. If we were to do that I would expect we would do something that is type erased. i.e. you could call a getter on the juce::AudioWorkgroup object that returned a void* which the user would then have to know to cast to an os_workgroup_t. The user would also have to deal with the responsibilities that carries such as incrementing and decrementing the ref count on the object!

Hi and thanks!

Yes you’re right, I was imprecise in my formulation, the threads are indeed upgraded to realtime first (that’s all in the internals of the library in question). It’s possible with thread_policy_set(…).

Yes indeed - I am also aware of the corresponding discussion on the Steinberg forum, where the status as of May is that it’s still work in progress.

I can see why you would!

That could be a helpful shortcut still, short of having to write all the Apple-AU-boilerplate to get the info directly through their API.

For now I’ll look into using the Apple API’s directly - in the AU case specifically - to see if I can glean that information.