I’m working on a plugin that has a variable latency (depending on some parameters) and I’m trying to figure out how to best handle this. As the latency can get quite long (up to 200ms), I don’t want to always report (and implement) the maximum possible latency.
What I’m currently doing is update the reported latency immediately as the underlying parameters are changed. Hosts seem to act on this information very differently.
ProTools for example is amazing in this regard, as it just updates its latency compensation on the fly while the sequencer is running. Parallel tracks stay in sync und the changes aren’t noticeable.
Logic on the other hand updates latency compensation upon starting/stopping the sequencer. So when I adjust my parameters while it’s running, the tracks go out of sync and when I restart the sequencer it’s fine again (which is really awful from a user perspective).
I’d like to implement a smarter scheme, but for that I guess I’d somehow need to know what the host is doing in terms of compensation. Is there any way to find out when the host updates or actually uses the supplied latency?
All solutions I could think of so far are rather hacky and may lead to even more problems. So I’m kinda stuck, maybe someone here has a good idea or has solved this puzzle elegantly in the past?
afaik there is absolutely no way to know whether the host has reacted to requested changes. And yes, hosts do react very differently to latency changes, but there’s not much you can do about it besides telling your users to use a better host ;).
If you have parameters that lead to finely adjustable latency and don’t always want to report the max latency, I suggest doing a few latency tiers… so if you have 200ms max, just report 0/10/50/100/200 ms and make up for the rest internally. That way you can reduce the number of latency change calls needed and get fewer weird playback states. At the same time, you can try to not report the latency if it goes down until playback stops when all hosts are able to adjust.
I also write in my manuals that latency changes are not handled very well by some hosts and might require a start/stop cycle to work correctly.
Yeah, I guess that latency thing will be something that needs to be in FAQs, it’s probably impossible to implement a solution that doesn’t behave in a confusing way in some circumstances and some hosts.
The idea with the latency tiering is great though, I’ll try how it feels if I do that and only report updated latency only in prepareToPlay() or something like that.
I would personally suggest to report the max latency all the time, or at least have a setting to do so.
As you noticed because some hosts deal with changes only on stop/start, I would be super annoyed as a user if moving a knob during playback would get my track out of sync.
Worse, think about a case where a user automates a parameter that makes the latency go from 0 to 200ms: if you let the latency change dynamically during playback, continuously or by steps, it’ll be literally unusable for users in Logic and other DAWs that update their graph only on stop/start
I think the reason I want variable latency is to somehow have an as-low-as-possible latency for the case when it’s in a realtime path and users are playing through it. So it would be cool to have lower latency if possible. But that creates all kinds of implications as discussed.
Just checked in Logic, and their Adaptive Limiter has adjustable Lookahead and behaves very similarly to my first approach: when adjusting it while sequencer is running, the track goes out of sync and resyncs upon restart. But I probably don’t want to take that as an excuse to do it the same way.
Right now I tend towards fixed maximum latency as a default and a switchable “low latency mode”. That way latency can only change and mess sync up when the user pushes a button with the word “latency” on it, which should be more transparent and tolerable.
200ms all the time is not a good solution for a plugin with adjustable latency because that makes it unusable for real-time things like record monitoring or on-stage usage.
It for sure depends on the nature of the plugin, and most importantly on the use case.
That’s why I suggested making it at least an option.
Something like “Report constant latency”. Makes everyone happy