Install from ReaPack (highly recommended) or download from GitHub.
Cubase/Logic style low latency monitoring mode for REAPER.
New streamlined and strongly opinionated version as C/C++ plug-in extension.
Same core functionality as before but with no user setting 'hassle'.
Assumes per-chain PDC compensation mode (default in REAPER version > 6.19). Works with other modes too in a kind of 'will not break things' way.
Plugins can now be manually enabled/bypassed while ReaLlm: Low latency monitoring is running, and manual user choices are persistent. This makes previous including/excluding plugins or tracks with tags obsolete.
Hard limit is no longer available. No separate PDC or individual plugin limit settings. PDC limit is set to one audio driver block/buffer, but can changed with Llm_Set(). This should leave enough 'PDC headroom' to begin with. It's now just easier and faster to 'manually override' plugins anyway.
Simpler and, hopefully, more robust.
Also provides ReaScript API functions.
Documentation in Help > ReaScript Documentation...
ak5k_Low latency monitoring
Provides REAPER a function also known as Low Latency Monitoring, Low Latency Mode, Native Low Latency Monitoring, Constrain Delay Compenstation, Reduce Latency when Monitoring etc. It resembles the one from Cubase.
While enabled, it takes offline/bypasses latency inducing plugins (VSTs etc) from project and rec armed and/or input monitored signal chains, to provide lowest possible latency and CPU usage when monitoring through software.
Plugins contributing PDC latency to monitored signal chain will be bypassed, once the set limit is exceeded per signal chain. Useful when recording e.g. software synths or guitars through amp sims into a REAPER project already filled with plugins.
Can be setup as a toolbar toggle on/off button, and this is recommended. Parameters can be configured.
Configurable parameters:
Code:
Latency limit: (in ms)
Safe tagging: (1=yes, 0=no)
Safe tag: (e.g. -LL)
Plugin limit: (in ms)
Include master: (1=yes, 0=no)
Enable report: (1=yes, 0=no)
Hard limit: (1=yes, 0=no)
Latency limit: (in ms)
The maximum allowed target latency for the script to pursue, including audio device latency. For example, if limit is set to 8 ms, and device latency is 5 ms, script will allow 3 ms worth of plugin latency in monitored signal chain. The script won't take PDC disabled plugins into account. Input FX and Monitoring FX are left untouched.
Safe tagging: (1=yes, 0=no) Safe tag: (e.g. -LL)
Allows individual tracks and plugins to be left untouched by safe tagging. This is done by appending safe tag string to track or plugin name in Reaper. Safe tagged tracks and plugins are not included in the overall result calculation. Default tag is "-LL", without the quotes. E.g. Rename FX instance... > "Awesome Sound Betterer 3 -LL".
Plugin limit: (in ms)
Allows plugins below this latency stay enabled, even if the total limit is exceeded. Setting this to zero will always disable all latency inducing plugins from signal chain after the point where limit is exceeded, and zero is the recommended setting. Individual plugins/tracks can be safe tagged. To my understanding, as REAPER allocates plugins into discrete blocks, resulting latency isn't a linear sum of individual plugin (or FX chain in >6.19 versions) PDC latencies, but the sum of blocks each plugin/FX chain takes. Please correct if this isn't so. *Updated the script to support this.
Include master: (1=yes, 0=no)
Not including the Master Track will leave Master Track untouched. It's usually good to leave this on. In most cases, the latency inducing and CPU heavy plugins are found in the Master, if nowhere else. If monitored signal chain is disconnected from Master, and routed only to separate outputs, then Master will naturally be excluded, but it seems discrete routings to separate hardware outputs are still delayed to match Master (or other 'with-most-PDC' signal chain in the project), unless Master track plugins PDC is manually disabled.
Enable report: (1=yes, 0=no)
Opens up a crude and annoying cute and delightful message window, which shows the actual resulting latency including audio device, driver and overall plugin latency. It will always show audio device driver latency at current buffer/block size.
By extending the window, it will show information about PDC latency inducing (non-bypassed or online) plugins in the currently active monitored signal chain. It generally prints tracks in no particular order. Setting Latency limit very high and turning off Hard limit will practically turn the script into an analysis tool.
Hard limit: (1=yes, 0=no)
In Hard limit mode, the script 'modally' takes offline all plugins with PDC latency 512 or greater, and restores them once script is turned off.
Guide
Assign a toolbar button or keyboard command to enable/disable the script. Recommended use is to setup recording/monitoring related things first, arm inputs, and then enable the script, if performance and/or latency related issues arise.
The script is basically a toggle on/off background service, but it isn't constantly processing or 'running' things. It keeps track of change in the monitored signal chain, and only reacts to change 'on-demand'. Tested with native REAPER plugins, Waves, FabFilter and UAD-2 -VSTs without troubles.
Achieving lowest possible latency with software monitoring requires a low latency signal chain in DAW, and user to set a low audio device block/buffer size. This in turn increases CPU power requirements. Enabling hard limit mode can help with this, as it takes offline plugins with high (512 or greater) PDC latency, which usually take more CPU too.
Simple instructions:
1. [your monitoring/recording preparations]
2. Change block/buffer size to lowest possible your CPU and audio device can survive with moderate load (optional).
3. Safe tag any plugins or tracks that need to stay online (optional).
4. Arm tracks (optional, recommended).
5. Turn on ak5k_Low Latency Monitoring.
6. Modify settings (optional).
7. Record/monitor.
To some extent, the monitored signal chain can be modified while keeping the script on, and the script will be able to take this into account. Tracks can be added or removed, and routings can change. Copying or moving a plugin bypassed/offlined by the script from monitored signal chain to unmonitored track may cause 'buggy' behavior while the script is enabled. In Hard limit mode large amount of offlined plugins may cause excessive loading times.
Stores information of plugins it handles into project extension specific state. This way script 'remembers' plugins it has offlined or bypassed between open sessions, as long as the project is saved. Example: 1) Leaving a project while script is enabled, inputs are armed and some plugins are taken offline/bypassed by the script. 2) Returning into the project with the script disabled. 3) Previously offlined/bypassed plugins still remain offline/bypassed. 4) 'Cycling' the script on/off once will restore the original state.
Video and .gifs below might be outdated (e.g. some names) on some parts.
Basic operation
More basic operation
Hard limit: 1 (=yes)
Safe tagging: (1=yes, 0=no) Safe tag: (e.g. -LL)
Enable report: (1=yes, 0=no) Pro tip
By setting Latency limit very high, e.g. over 9000, and turning off Hard limit mode, the script will effectly do nothing, except print the information considering monitored signal chain and it's PDC latency inducing plugins. This information can be revealed by extending the report window, and can be used as a manual analysis tool, and is shown in the .gif below.
pdc_manager = true -- or false
Basically overrides automatic PDC for monitored signal chains, and performs 'old-school pen-and-paper' style time aligning to maintain sync, and to achieve lower latency. Uses "JS: Time Adjustment Delay" plugins for this (1 instance per 2 track channels). Takes control over all "JS: time_adjustment" named plugins in monitored signal chain. This option is slightly experimental.
Improved handling of plugin copies and duplicate tracks
Thanks! I've been testing and just updated the script, so I recommend downloading new version from the link.
Clickable icon reflecting the state is possible:
First install Reaper SWS / S&M Extension, if you haven't already.
Customize your toolbar (right click).
Choose 'Add...' and select 'Script: ak5k-low-latency-monitoring.lua' .
If you haven't yet loaded the script, choose 'New Action...', 'Load ReaScript...' and browse for the 'ak5k-low-latency-monitoring.lua' file you downloaded.
If you're updating, I recommend first to remove the old action and script file, and then load the new one.
You can rename the button or add an icon to it.
After first runtime, it will ask to Terminate Instances for the script. Choose option 'Remember my answer for this script' and then choose 'Terminate Instances'.
There might still be some bugs in the behaviour, but On/Off toggling the script button or disable/re-enable rec/input monitoring on a track refreshes the state of low latency monitored signal path.
My friend, this is absolute incredible.
Like, this should just exist in Reaper of course haha, but thank you for creating it. Latency gets so bad once using things like Soothe and Limitless - to the point of discouraging adding more VSTi. This solves it.
Is there any chance that things can go really wrong with this? Like what happens if the project crashes while the script is running? Will the state of the plugins suddenly be all screwed up?
...just scared to run it in some big pop project with a budget and deadline, and suddenly things are disabled that shouldn't be, and it's impossible to tell which ones I disabled myself and which the script temporarily did for latency reduction...
Like, this should just exist in Reaper of course haha, but thank you for creating it. Latency gets so bad once using things like Soothe and Limitless - to the point of discouraging adding more VSTi. This solves it.
Is there any chance that things can go really wrong with this? Like what happens if the project crashes while the script is running? Will the state of the plugins suddenly be all screwed up?
Quote:
Originally Posted by ferropop
...just scared to run it in some big pop project with a budget and deadline, and suddenly things are disabled that shouldn't be, and it's impossible to tell which ones I disabled myself and which the script temporarily did for latency reduction...
Thanks!
It uses ReaScript project extension specific state to store data, so to my understanding this wouldn't be able to corrupt the main project file. The script 'knows', reads and writes data (a list of plugins it disables/enables). It has it's own small and simple internal data structure for that.
During playback or recording (or transport running in general) the script in effect does nothing, except for waiting the playback/recording/transport to stop.
You can set the total maximum allowed signal chain latency by applying a simple edit to the script file. Changing the 'local latency_limit' variable (defaults to 16), at the top of the script file, with a value more suitable for your needs. E.g. some amp simulators might require a larger value to stay enabled.
In it's current state I haven't been able to 'crash' the script with humanly interaction. E.g. manipulating the signal path or changing plugins etc while keeping it enabled. It can handle Track FX/plugins on chains with nested tracks, track folder structures, track sends, master track (purpously ignores monitoring FX section), and also handles negative feedback loop signalchains (A send to B > B send back to A). To my understanding, it now also correctly handles separate states for different projects.
Only issue so far I've encountered is when I use the Low Latency Monitoring script in project A, then switch to project B, turn off Low Latency Monitoring, switch back to project A, project A plugins are still disabled. Then have to manually once toggle the script on and off to restore back the normal state. Although I think this flipping the script state over could be set up as a default action for opening/changing project, so it would take care of that.
Just tested with a test project of 30 nested track folders each including subfolders to depth of 4, totaling to 120 tracks in project, and then enabling record/input monitoring for all 120 tracks at the same tame (the bottom level inputs and their parent folders), some of them including randomly dragged sends between each other, and some purpously set negative feedback loop sends, and the script didn't even 'flinch', but tracked the signal chains and disabled plugins. Running on an average 2016 desktop PC.
It uses ReaScript project extension specific state to store data, so to my understanding this wouldn't be able to corrupt the main project file. The script 'knows', reads and writes data (a list of plugins it disables/enables). It has it's own small and simple internal data structure for that.
During playback or recording (or transport running in general) the script in effect does nothing, except for waiting the playback/recording/transport to stop.
You can set the total maximum allowed signal chain latency by applying a simple edit to the script file. Changing the 'local latency_limit' variable (defaults to 16), at the top of the script file, with a value more suitable for your needs. E.g. some amp simulators might require a larger value to stay enabled.
In it's current state I haven't been able to 'crash' the script with humanly interaction. E.g. manipulating the signal path or changing plugins etc while keeping it enabled. It can handle Track FX/plugins on chains with nested tracks, track folder structures, track sends, master track (purpously ignores monitoring FX section), and also handles negative feedback loop signalchains (A send to B > B send back to A). To my understanding, it now also correctly handles separate states for different projects.
Only issue so far I've encountered is when I use the Low Latency Monitoring script in project A, then switch to project B, turn off Low Latency Monitoring, switch back to project A, project A plugins are still disabled. Then have to manually once toggle the script on and off to restore back the normal state. Although I think this flipping the script state over could be set up as a default action for opening/changing project, so it would take care of that.
Just tested with a test project of 30 nested track folders each including subfolders to depth of 4, totaling to 120 tracks in project, and then enabling record/input monitoring for all 120 tracks at the same tame (the bottom level inputs and their parent folders), some of them including randomly dragged sends between each other, and some purpously set negative feedback loop sends, and the script didn't even 'flinch', but tracked the signal chains and disabled plugins. Running on an average 2016 desktop PC.
This is incredible. I can't even express how much of a difference this will make to people's workflow. No more freezing!
The one thing I wonder -- if you were to Save the project while those plugins are disabled by the script, and Reaper were to crash before the plugin state is restored - will the .rpp (or rppbak) file incorrectly have saved the disabled plugin states?
Do you know what I mean? Just terrified of a situation where there's a crash, and the save (or backup) now has the toggled state saved with no way to return.
This is incredible. I can't even express how much of a difference this will make to people's workflow. No more freezing!
The one thing I wonder -- if you were to Save the project while those plugins are disabled by the script, and Reaper were to crash before the plugin state is restored - will the .rpp (or rppbak) file incorrectly have saved the disabled plugin states?
Do you know what I mean? Just terrified of a situation where there's a crash, and the save (or backup) now has the toggled state saved with no way to return.
I understand your concern. To my understanding, the disabled/enabled state of plugins stores into the 'main' project file state. The script stores it's own separate list of 'Plugins, me the script, disabled' into the project extension specific state.
Again, to my understanding, if Reaper crashes, neither of these get written into the project file. Or vice versa, both of them get written when saved, or automatically backed up.
Basically, when turned/toggled on, the script starts to continuosly scan rec/monitoring enabled signal chains, disables plugins after latency limit is exceeded for every monitored signal chain, and stores the list of disabled plugin individual GUIDs into project. Just to point out, for example it doesnt disable 'record-armed-but-not-monitored' signal chains.
When turned/toggled off, it then reads back and clears the list of disabled plugins from the project extension specific state, and enables the plugins, restoring the normal state.
In between, it basically repeats this as long as it's enabled, and transport is not running.
So to my understanding, it's practically not possible for the project to crash so, that the main project state would contain information of the plugins being disabled, but the extension state would not contain the list of plugins disabled by the script. I think it would be both or neither.
Discovered a second 'issue' for real life situations. If a track with Low Latency Monitoring disabled plugins is duplicated (while running Low Latency Mode), the duplicate track will have these plugins as manually disabled, so turning off LLM will not re-enable these. But I don't think the scripting API offers anything to track this, unless there's a way to get a 'bang' for this.
Anyways, each 'pass' of the script registers as a single undoable/redoable action called 'Low Latency Monitoring'. In other words, every time when the script enables or disables plugins, this can be undone/redone with standard Ctrl (+ Shift) + Z, once the Low Latency Monitoring script is turned off. As long as this information gets stored in the main project file, all changes the script does can be rolled back or be redone. Just as you can undo/redo any other stuff. But if you manually undo the changes made by the script, it won't keep track of these, as they're users actions.
Updated the script again. Now it takes the desired latency limit in as milliseconds. It also no longer relies on the SWS / S&M Extension.
Seriously - great work! I made a FR for this as I actually didn't think it would be possible via scripting.
Have you noticed any performance hit from having this script running? I keep my Vsti's in 'automatic record arm when track selected' mode - could you foresee any issues with that interacting with this script?
I'm just playing around with it, and literally the only downside of this script now compared to studio one (which is the only other DAW I've used with this function), is that you are still constrained to the minimum buffer size setting of your audio interface, whereas in Studio One (and Logic too I believe?) you can actually set two individual buffer sizes, a 'live' one and a 'playback' one.
I totally understand why it might not be possible, but if you can find a way to allow us to set a different buffer size within the script for armed channels, that would be incredible. I know you can have Reaper 'request' a block size from the audio interface, but how reliable this is, and how smoothly it interacts with the wide variety of interface drivers out there is another question!
This is phenomenal man, thanks for your efforts. I'm surprised more people aren't jumping all over this.
Quote:
Originally Posted by Joe90
AMAZING!
Seriously - great work! I made a FR for this as I actually didn't think it would be possible via scripting.
Have you noticed any performance hit from having this script running? I keep my Vsti's in 'automatic record arm when track selected' mode - could you foresee any issues with that interacting with this script?
I'm just playing around with it, and literally the only downside of this script now compared to studio one (which is the only other DAW I've used with this function), is that you are still constrained to the minimum buffer size setting of your audio interface, whereas in Studio One (and Logic too I believe?) you can actually set two individual buffer sizes, a 'live' one and a 'playback' one.
I totally understand why it might not be possible, but if you can find a way to allow us to set a different buffer size within the script for armed channels, that would be incredible. I know you can have Reaper 'request' a block size from the audio interface, but how reliable this is, and how smoothly it interacts with the wide variety of interface drivers out there is another question!
Anyway, awesome work! Thank you.
Thank you guys.
I don't think I can get the script to change buffer size, unless a method for this is provided natively within the ReaScript. I also have been hoping for this to be possible. On Windows platform, ASIO buffer size is usually adjusted from the audio interface driver, not DAW. But to my knowledge none of the major DAWs provide separate buffer sizes for latency monitoring, although I haven't used Studio One. I know for certain that Cubase, Logic and Pro Tools only bypass plugins, and don't change buffer size. Logic is good at making users think otherwise.
I haven't noticed any significant performance hit. The script relies heavily on simple and/or native Lua functions and ReaScript, so I would believe they have been optimized quite well, even though the script itself does a lot of looping and recursion. I'm not very familiar with the inner workings of Lua scripting language or ReaScript.
Once again, I updated the script. Now it includes 3 user settings. Small documentation in the script itself. Latency limit is now based on total roundtrip latency calculated from sample rate, buffer size and monitored signal chain latencies.
Code:
local latency_limit = 6
So setting it somewhere around 5 to 10 ms will work for buffer size 64 when recording.
Also, it is now possible to set an individual plugin latency 'allowance' in ms.
Code:
local plugin_limit = 2
This basically 'whitelists' all plugins under this latency, leaving them enabled even if the monitored signal chain has exceeded it's maximum limit. Setting this to 0 effectively disables all plugins once monitored signal chain latency limit is reached.
And now by default it opens a console window, which shows the current total roundtrip monitoring latency at current monitored signal chain. This can be enabled/disabled by setting the
Code:
local enable_report = true or false
This is good for 'analyzing' or 'debugging' your project. Saw someone talking about this on the FRs and thought it could be useful information, and a nice gimmick.
If you mean the MPL script which disables all plugins over PDC latency N, then this works in a different way. This scans for monitored input tracks, then based on those input tracks, builds all possible discrete (and active/monitored) signal chains, and for those discrete signal chains, starts to disable plugins once the maximum allowed latency is exceeded in the signal flow per chain.
In other words, it disables only plugins from tracks within monitored signal chains, leaving rest of the project 'untouched'. To provide same functionality as Low Latency Monitoring in other mainstream DAWs.
I'm currently making a complete rewrite to improve performance, as the current version starts to choke around 300 monitored input tracks, at least on my computer.
The script seems strange, there's the latency monitoring script, and putting it as a toolbar button makes it so that when you go to click it on and off, it asks you to make a new instance or terminate instances
The script seems strange, there's the latency monitoring script, and putting it as a toolbar button makes it so that when you go to click it on and off, it asks you to make a new instance or terminate instances
What would be the proper settings for not allowing any plugin more than 64 samples of latency, for instance? I see only ms. I will read more I promise.
What would be the proper settings for not allowing any plugin more than 64 samples of latency, for instance? I see only ms. I will read more I promise.
That depends on project sample rate. But if you're running 'standard' 44 or 48 k, then
Code:
local plugin_limit = 1.4
would do around 64 samples.
BTW. I'm rigorously working on new version, so never mind if there are some slight inconsistencies with the script. Mainly related to more complex routings and possibly trying to figure out how to handle Duplicate Tracks.
That depends on project sample rate. But if you're running 'standard' 44 or 48 k, then
Code:
local plugin_limit = 1.4
would do around 64 samples.
BTW. I'm rigorously working on new version, so never mind if there are some slight inconsistencies with the script. Mainly related to more complex routings and possibly trying to figure out how to handle Duplicate Tracks.
I truly appreciate it.
Maybe there could be a popup that comes up with some settings and also shows the latency. Something that can be docked or in some permanent place out of the way. What is the utility of this output? can you make it so the window closes after you stop the script?
Did you explain how this latency figure it calculated? Is it the soundcard round trip plus any monitoring latency?
I am running my RME FF800 at 6.8/7.9 ms, and your console output says 14.8 and I have a local latency limit of 6 and a plugin limit of 1.
What i like is it seems to bypass plugins WHILE you have it on, if you record arm a track that is introducing latency!!!
Last edited by Jae.Thomas; 12-03-2020 at 01:53 PM.
Maybe there could be a popup that comes up with some settings and also shows the latency. Something that can be docked or in some permanent place out of the way. What is the utility of this output? can you make it so the window closes after you stop the script?
Did you explain how this latency figure it calculated? Is it the soundcard round trip plus any monitoring latency?
I am running my RME FF800 at 6.8/7.9 ms, and your console output says 14.8 and I have a local latency limit of 6 and a plugin limit of 1.
What i like is it seems to bypass plugins WHILE you have it on, if you record arm a track that is introducing latency!!!
Yes, that's is the main, and only, function of Low Latency Monitoring; to bypass latency inducing plugins from rec armed/monitored signal paths to help recording through software with lower latency. Very useful with semi complete sessions, where you need punch in software synths or guitars through amp sims etc. Or just to record something into a project with a ton of PDC expensive plugins with software monitoring. I think the current version should take driver IO + total monitor path latency. It gets the driver IO by a native ReaScript API call, but it might do some errors when accounting the total, but it shouldnt be any less than driver latency. Already fixed in the yet unpublished version. Some kind of GUI certainly would be nice. Maybe some day. Currently I've been implementing completely new 'brains for the new version. Just tested with 500 tracks, each with 4 plugins, 2 of them which induce latency, and tracks themselves are in several nested layers and include sends between. Armed them all simultaniously with Select All.., and it took around 0.2 seconds and 4 MB of RAM for the new 'brain' and algorithm to calculate all possible discrete routes, disable appropriate plugins and store the information. 2016 average PC.
Any chance of getting a video on what this cool script does?
It would be a boring vid, and if I had the older (working) version of the script I would easily make one.
IF you have tracks which are being monitored (let's say you are playing guitar through an amp plugin)
and
IF that track OR ANYTHING it goes through (folders or the master) has latency inducing plugins above X value (you set that), those plugins get disabled and remembered.
AFTER you are done, you can click it again to restore the plugins you disabled out of bypass.
From my tests, it even seems that if you turn a plugin back on in the middle, it will know you turned it on and not toggle it to bypass when you click the command.
Whats great about this is that you can set a toolbar button to it, and you can easily see when it is on, which is an advantage for me over MPL's script along with an all in one solution and customization
instead of editing the action within reaper, deleting and replacing with the text above, I went right to the text file and replaced the contents.
Opened reaper, turned on latent plugins with a record armed track (it is record armed immediately because it's my default)
triggered the action, no response.
Added fx to the track and this comes up
ak5k-low-latency-monitoring.lua:434: attempt to index a nil value (global 'trackfx_data')
Updated to fix this. The new version didn't initialize a 'plugin database variable', because it tried to read the 'database' set by older version. Now new (and fortcoming) version handles this situation properly. This is kind of embarrasing, because I didn't take into account the situation, where someone would actually have used the previous version.
Updated to fix this. The new version didn't initialize a 'plugin database variable', because it tried to read the 'database' set by older version. Now new (and fortcoming) version handles this situation properly. This is kind of embarrasing, because I didn't take into account the situation, where someone would actually have used the previous version.
for some reason, the script isn't doing anything for me. It IS showing on and off and reporting latency tho... and I have some massive lateny plugs on here
in my default template, I have a tuner track, which is hidden but always armed (not recording tho) and monitored. I make it so that I always have access to a tuner from my DI input regardless of what track I'm on, or If I'm on any track.
Would it be possible to exclude certain tracks named a certain way?
in my default template, I have a tuner track, which is hidden but always armed (not recording tho) and monitored. I make it so that I always have access to a tuner from my DI input regardless of what track I'm on, or If I'm on any track.
Would it be possible to exclude certain tracks named a certain way?
Good to hear!
I'm thinking of adding a tag based 'white list' function. If a plugin name contains this tag, it will never get bypassed.
For example, if the end tag for plugin name is "-LLM", then all plugin names ending with this tag will be left untouched. All you have to do is to give the plugin a custom name.
This will be relatively simple to implement, as ReaScript API offers native method for checking TrackFX's custom names.
I'm thinking of adding a tag based 'white list' function. If a plugin name contains this tag, it will never get bypassed.
For example, if the end tag for plugin name is "-LLM", then all plugin names ending with this tag will be left untouched. All you have to do is to give the plugin a custom name.
This will be relatively simple to implement, as ReaScript API offers native method for checking TrackFX's custom names.
well, what I'm actually asking is if the script can leave certain tracks out of the equation. although my reatune track is always armed, it doesn't need to be considered for the script.