Add some example Lua scripts
This commit is contained in:
parent
2579e70f46
commit
756c5a5ee1
160
scripts/_rubberband_swing.lua
Normal file
160
scripts/_rubberband_swing.lua
Normal 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
|
14
scripts/_tempo_map_dump.lua
Normal file
14
scripts/_tempo_map_dump.lua
Normal 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
|
Loading…
Reference in New Issue
Block a user