13
0

Add some example Lua scripts

This commit is contained in:
Robin Gareus 2020-01-14 16:52:42 +01:00
parent 2579e70f46
commit 756c5a5ee1
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
2 changed files with 174 additions and 0 deletions

View File

@ -0,0 +1,160 @@
ardour {
["type"] = "EditorAction",
name = "Swing It (Rubberband)",
license = "MIT",
author = "Ardour Team",
description = [[
Create a 'swing feel' in selected regions.
Analyze beat-position from the selected audio regions,
then time-stretch the audio and move 8th notes back in
time while keeping 1/4 note beats in place.
(This script also servers as example for both VAMP
analysis as well as Rubberband region stretching.)
Kudos to Chris Cannam.
]]
}
function factory () return function ()
-- helper function --
-- there is currently no direct way to find the track
-- corresponding to a [selected] region
function find_track_for_region (region_id)
for route in Session:get_tracks ():iter () do
local track = route:to_track ()
local pl = track:playlist ()
if not pl:region_by_id (region_id):isnil () then
return track
end
end
assert (0) -- can't happen, region must be in a playlist
end
-- get Editor selection
-- http://manual.ardour.org/lua-scripting/class_reference/#ArdourUI:Editor
-- http://manual.ardour.org/lua-scripting/class_reference/#ArdourUI:Selection
local sel = Editor:get_selection ()
-- Instantiate the QM BarBeat Tracker
-- see http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR:LuaAPI:Vamp
-- http://vamp-plugins.org/plugin-doc/qm-vamp-plugins.html#qm-barbeattracker
local vamp = ARDOUR.LuaAPI.Vamp ("libardourvampplugins:qm-barbeattracker", Session:nominal_sample_rate ())
-- prepare undo operation
Session:begin_reversible_command ("Rubberband Regions")
local add_undo = false -- keep track if something has changed
-- for each selected region
-- http://manual.ardour.org/lua-scripting/class_reference/#ArdourUI:RegionSelection
for r in sel.regions:regionlist ():iter () do
-- "r" is-a http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR:Region
-- test if it's an audio region
local ar = r:to_audioregion ()
if ar:isnil () then
goto next
end
-- create Rubberband stretcher
local rb = ARDOUR.LuaAPI.Rubberband (ar, false)
-- the rubberband-filter also implements the readable API to read from
-- the master-source of the given audio-region (ignoring any prior time-stretch
-- or pitch-shiting).
-- https://manual.ardour.org/lua-scripting/class_reference/#ARDOUR:Readable
local max_pos = rb:readable ():readable_length ()
-- prepare table to hold analysis results
-- the beat-map is a table holding audio-sample positions:
-- [from] = to
local beat_map = {}
local prev_beat = 0
local pdialog = LuaDialog.ProgressWindow ("Rubberband", true)
-- callback to handle Vamp-Plugin analysis results
function vamp_callback (_, pos)
return pdialog:progress (pos / max_pos, "Analyzing")
end
function rb_progress (_, pos)
return pdialog:progress (pos / max_pos, "Stretching")
end
-- run VAMP plugin, analyze the first channel of the audio-region
vamp:analyze (rb:readable (), 0, vamp_callback)
-- getRemainingFeatures returns a http://manual.ardour.org/lua-scripting/class_reference/#Vamp:Plugin:FeatureSet
-- get the first output. here: Beats, estimated beat locations & beat-number
-- "fl" is-a http://manual.ardour.org/lua-scripting/class_reference/#Vamp:Plugin:FeatureList
local fl = vamp:plugin ():getRemainingFeatures ():at (0)
local beatcount = 0
-- iterate over returned features
for f in fl:iter () do
-- "f" is-a http://manual.ardour.org/lua-scripting/class_reference/#Vamp:Plugin:Feature
local fn = Vamp.RealTime.realTime2Frame (f.timestamp, Session:nominal_sample_rate ())
beat_map[fn] = fn -- keep beats (1/4 notes) unchanged
if prev_beat > 0 then
-- move the half beats (1/8th) back
local diff = (fn - prev_beat) / 2
beat_map[fn - diff] = fn - diff + diff / 3 -- moderate swing 2:1 (triplet)
--beat_map[fn - diff] = fn - diff + diff / 2 -- hard swing 3:1 (dotted 8th)
beatcount = beatcount + 1
end
prev_beat = fn
end
-- reset the plugin (prepare for next iteration)
vamp:reset ()
if pdialog:canceled () then goto out end
-- skip regions shorter than a bar
if beatcount < 8 then
pdialog:done ()
goto next
end
-- now stretch the region
rb:set_strech_and_pitch (1, 1)
rb:set_mapping (beat_map)
local nar = rb:process (rb_progress)
if pdialog:canceled () then goto out end
-- hide modal progress dialog and destroy it
pdialog:done ()
pdialog = nil
-- replace region
if not nar:isnil () then
print ("new audio region: ", nar:name (), nar:length ())
local track = find_track_for_region (r:to_stateful ():id ())
local playlist = track:playlist ()
playlist:to_stateful ():clear_changes () -- prepare undo
playlist:remove_region (r)
playlist:add_region (nar, r:position (), 1, false, 0, 0, false)
-- create a diff of the performed work, add it to the session's undo stack
-- and check if it is not empty
if not Session:add_stateful_diff_command (playlist:to_statefuldestructible ()):empty () then
add_undo = true
end
end
::next::
end
::out::
-- all done, commit the combined Undo Operation
if add_undo then
-- the 'nil' Command here mean to use the collected diffs added above
Session:commit_reversible_command (nil)
else
Session:abort_reversible_command ()
end
vamp = nil
collectgarbage ()
end end

View File

@ -0,0 +1,14 @@
ardour { ["type"] = "Snippet", name = "Tempo Map Dump" }
function factory () return function ()
local tm = Session:tempo_map ()
local ts = tm:tempo_section_at_sample (0)
while true do
print ("TS @", ts:sample(), " | ", ts:to_tempo():note_types_per_minute (), "..", ts:to_tempo():end_note_types_per_minute (), "bpm")
ts = tm:next_tempo_section (ts)
if not ts then break end
end
end end