Please can you provide some examples of plugins for which the current behaviour is problematic?
Unfortunately the documentation for the mHostTime field is a bit opaque, but it is hinted that the host time should be derived from AudioGetCurrentHostTime or mach_absolute_time. It sounds like calling these functions on each render callback is introducing jitter. An alternative approach might just be to increment the current host time by the buffer duration on each process callback, but I’d like to test out this approach to see whether it works in practice.
Thanks for that. I’ve tested a bit with some simple loops, but as far as I can tell the timing seems alright with and without my potential fix. I’m guessing that the project has to be set up in a certain way for the problem to become evident.
Please can you try applying this change and see whether it resolves the issue you were seeing?
If this patch doesn’t resolve the problem, please provide some instructions so that I can properly reproduce the issue locally. If you have e.g. an AudioPluginHost project that exhibits the problem that would be useful.
The issue with the stable increment of the host time is resolved with the patch, in fact Loopy Pro now seems to be able to render properly. But it seems to break all other plugins: some of them crash, some make some weird sound, some don’t emit any sound. Easily reproducible in the AudioPluginHost.
Thanks for testing that out. Unfortunately I don’t have a great selection of AUv3 plugins to test with, and as I said previously Loopy Pro seemed to behave correctly before and after the proposed change. Are you testing on a specific device? I’ve been using an iPhone SE 2, but I wonder whether the problem is more obvious on other devices.
I had a look at propagating the audio callback timestamp through to the plugins, but this looks like it could be quite a substantial (possibly breaking) change. To get the timestamp into the plugin, it would probably need to go via the AudioPlayHead in order to maintain source compatibility, and the AU wrapper would need to extract this information and do something sensible if it was not set. We’d also need a way of signalling whether or not this timestamp held a valid value (it wouldn’t for JUCE plugin clients, for example). We’d also need to add timestamp support to the AudioIODevice - for consistency, I’d want to add this for all audio device types, or at least provide an API capable of supporting all device types in the future.
To be clear, I’m not dismissing this approach completely. However, I’m keen to try out other approaches too, in case the issue can be resolved with a less disruptive change.
I notice that the AudioTimeStamp struct has a flags field that allows the host to specify which members are valid. I tried removing kAudioTimeStampHostTimeValid from mFlags, zeroing mHostTime, and testing Loopy Pro in the AudioPluginHost, and it still seemed to work correctly. I tried a couple of other plugins too (Viking Synth and Filterstep) and those both seemed to cope too. Would you be able to test this out yourself and see how the results compare to the other approaches? Thanks!
I found a way to consistently reproduce one of the problems in the AudioPluginHost.
Since there’s no transport or playhead in AudioPluginHost, the trick is to use Ableton Link, with another peer on the network.
This is the setup:
add one instance of Loopy Pro
insert a loop in one of the circles
enable Link in the upper right menu > synchronisation
start Link from another device / app
if necessary tap on the loop to play it
The problem manifests when the loop restarts: you can hear a glitch or a silence.
For reference: it works fine when using the host time from the audio callback. Here’s a patch if you want to try it (it savagely passes the timestamp to the plugins )
Thanks, I’ve tried out those steps and haven’t been able to reproduce any glitching so far when the kAudioTimeStampHostTimeValid flag is not set. I do get glitching when building from develop, though. I’ll try a bit more.
Did you try disabling the mHostTime flag altogether like I suggested? Did this reduce or remove the glitching for you?
Thanks for your patience. I’ve now put together a patch that should provide a way of communicating the callback timestamp from the audio device all the way to a hosted audiounit. At the moment the timestamp goes via the AudioPlayHead, so you’ll need to override the new function on an AudioPlayHead instance and then pass this playhead to any hosted plugins in order for them to receive the correct timestamp information. I’ve implemented this for the AudioProcessorPlayer, so this should work automatically in the AudioPluginHost.
I’ve tested this patch a bit with Loopy Pro and it seems to improve the audio quality a little. I’d feel a lot more confident in the change if you could test it too and see whether it resolves the issues you were seeing.
At the moment, I’ve only implemented timestamp reporting for iOS. If the patch looks good to you, I can investigate adding support for other audio device types too. VST2 and VST3 formats additionally provide an interface for reading the host time in nanoseconds during the process callback, so I can investigate adding support for that too.
@reuk thank you so much for the patch, I made some preliminary tests and the problem with Loopy Pro seems to be gone.
We’ll do some more tests and let you know in the next few days