I always missed a kind of “track freezing / unfreezing” for Midi Tracks in Ardour, to save CPU ressources in projects, containing a lot of MIDI Instrument Tracks. You can find similar functions in many DAWs already.
So I made my first script in Lua, which is supposed to do that task.
Basically the script carries out the following steps:
- check if the track selection is valid for a “freeze” or an “unfreeze” action (is a single Midi Track selected or an Audio Track with a special prefix ('*** ')?)
- stop the transport, if it’s running.
- in case of a freeze operation: bounce the MIDI track to an audio region, create a new audio track with a special prefix and load the newly created region to that track. Then deactivate and hide the MIDI source track.
- in case of an unfreeze operation: remove the Audio-Freeze-Track and unhide / re-activate the MIDI source track.
Since I’m lacking of scripting experience, I guess, the code is quite messy, so suggestion on how to enhance the script would be highly appreciated.
In the current version of the script, you’ll need to confirm the removal of the audio track containing the bounced audio, whenever you run an “unfreeze” action, I hope to find a way, to fix that soon.
At this point I want to say “thank you” for the awesome support here in this forum!
Here’s the code, feel free to give me feedback or to enhance the code depending on your needs:
ardour {
["type"] = "EditorAction",
name = "MIDI Track Freeze",
author = "Toxonic",
license = "MIT",
description = [[This script is supposed to provide a "Track Freeze" function for MIDI Tracks, as you can find in severeal well-known DAWs. The goal is, to save CPU ressources in projects with many MIDI instrument tracks, which don't need to be edited. The contents of these tracks can be "frozen" (bounced) to an Audio track with a special Prefix ('*** ') In a next step, the 'source' MIDI Track gets deactivated and hidden in the track view. If you need to edit it again, you can 'unfreeze' the track again by selecting the Audio-Freeze-Track and run the script again. The Audio-Freeze-Track will then be removed and the MIDI Track will be re-activated and unhidden.]]
}
function factory (unused_params)
return function ()
-- function to get the MIDI track name from the Freeze Track name
function cropString(strg)
local trimmedString = string.gsub(strg,"*** ","")
return trimmedString
end
-- Function to find prefix ("*** ")
function findPrefix(strg)
local prefix = string.sub(strg,1,4)
return prefix
end
-- Function for Info Messages
function dialog (text)
LuaDialog.Message ("Information", text, LuaDialog.MessageType.Info, LuaDialog.ButtonType.Close):run ()
end
-- Stop playback
if Session:transport_stopped() == false then Session:request_stop(false, false, 0)
end
-- Set up variables
local selCount = Editor:get_selection().tracks:routelist():size() -- Number of selected routes (tracks)
local r = Session:route_by_selected_count(0) -- Get the (first) selected route (track)
local track = r:to_track() -- Cast the selected route to a track
local i = 0
local current_index
-- Check if selection is valid for "freezing" or "unfreezing""
if selCount < 1 then dialog("No track selected.\nPlease select a MIDI track to freeze or a valid Audio-Freeze-Track to unfreeze (Prefix '*** ').")
elseif selCount > 1 then dialog("Multiple tracks selected.\nPlease select a MIDI track to freeze or a valid Audio-Freeze-Track to unfreeze (Prefix '*** ').")
end
if selCount == 1 and r:data_type():to_string() == "midi" then -- Selection is valid for freezing!!!
-- Set up necessary variables to go on
local trackname = r : name() -- trackname
local audioTrackname = "*** "..trackname -- Audio trackname
local order = r:presentation_info_ptr():order() -- Get order number of MIDI track
dialog("You have selected MIDI track ’" .. trackname.."’ on lane # " .. order .." to freeze.") -- Output Info
-- Bounce full MIDI track to audio
track:bounce(ARDOUR.InterThreadInfo (),audioTrackname)
-- Deactivate MIDI track
r:set_active (false, nil)
-- Hide MIDI track
local rtav = Editor:rtav_from_route(r)
Editor:hide_track_in_display (rtav:to_timeaxisview(), false)
-- Create new audio track for bounced audio
local freezeTrack = Session:new_audio_track (2, 2, nil, 1, audioTrackname, order, ARDOUR.TrackMode.Normal, true)
-- Get playlist for new audio track
local playlist = freezeTrack:front():playlist()
-- Get regions of this session to import "frozen" audio region
local rl = ARDOUR.RegionFactory.regions()
-- Iterate over them
for x,y in rl:iter() do
-- Increase iteration counter variable
i = i + 1
-- Check regions for a specific name...
if y:name() == audioTrackname then
-- If it's a match, increase index for the most current version of the frozen" audio region
current_index = i
end
end
-- Reset iterator variable again
i = 0
-- Iterate over regions again...
for x,y in rl:iter() do
-- Increase iteration counter variable
i = i + 1
-- If iteration counter variable matches the index for the most current version of the "frozen" audio region...
if i == current_index then
-- ..add the corresponding region to the playlist...
playlist:add_region (y, Temporal.timepos_t(0), 1, false)
break -- ... and stop the loop
end
end
end
if selCount == 1 and r:data_type():to_string() == "audio" then -- selection is valid for unfreezing
local trackname = r : name() -- trackname
local midiTrackname = cropString(trackname)
local midiTrack = Session:route_by_name(midiTrackname)
if findPrefix(trackname) ~= "*** " then dialog("This Audio track is not a valid Audio-Freeze-Track.\nPlease select an Audio-Freeze-Track with the prefix '*** ' to proceed with unfreezing")
elseif selCount == 1 and r:data_type():to_string() == "audio" and findPrefix(trackname) == "*** " then -- Selection is a valid track
-- Remove the freeze-Audio track
Editor:access_action("Editor", "remove-track")
-- Activate the MIDI source track ...
midiTrack:set_active (true, nil)
-- ...and make it visible again
local rtav = Editor:rtav_from_route(midiTrack)
Editor:show_track_in_display (rtav:to_timeaxisview(), false)
end
end
end
end