--- /dev/null
+ardour {
+ ["type"] = "dsp",
+ name = "Simple Amp",
+ category = "Example",
+ license = "MIT",
+ author = "Ardour Lua Task Force",
+ description = [[
+ An Example DSP Plugin for processing audio, to
+ be used with Ardour's Lua scripting facility.]]
+}
+
+
+-- return possible i/o configurations
+function dsp_ioconfig ()
+ -- -1, -1 = any number of channels as long as input and output count matches
+ return { [1] = { audio_in = -1, audio_out = -1}, }
+end
+
+-- optional function, called when configuring the plugin
+function dsp_configure (ins, outs)
+ -- store configuration in global variable
+ audio_ins = ins:n_audio();
+ local audio_outs = outs:n_audio()
+ assert (audio_ins == audio_outs)
+end
+
+-- this variant asks for a complete *copy* of the
+-- audio data in a lua-table.
+-- after processing the data is copied back.
+--
+-- this also exemplifies the direct "connect and run" process function,
+-- where the channel-mapping needs to be done in lua.
+
+function dsp_runmap (bufs, in_map, out_map, n_samples, offset)
+ for c = 1,audio_ins do
+ -- Note: lua starts counting at 1, ardour's ChanMapping::get() at 0
+ local ib = in_map:get(ARDOUR.DataType("audio"), c - 1); -- get id of mapped input buffer for given channel
+ local ob = out_map:get(ARDOUR.DataType("audio"), c - 1); -- get id of mapped output buffer for given channel
+ assert (ib ~= ARDOUR.ChanMapping.Invalid);
+ assert (ob ~= ARDOUR.ChanMapping.Invalid);
+ local a = bufs:get_audio (ib):data (offset):get_table(n_samples) -- copy audio-data from input buffer
+ for s = 1,n_samples do
+ a[s] = a[s] * 2; -- amplify data in lua table
+ end
+ bufs:get_audio(ob):data(offset):set_table(a, n_samples) -- copy back
+ end
+end
--- /dev/null
+ardour {
+ ["type"] = "dsp",
+ name = "Simple Amp II",
+ category = "Example",
+ license = "MIT",
+ author = "Ardour Lua Task Force",
+ description = [[
+ An Example DSP Plugin for processing audio, to
+ be used with Ardour's Lua scripting facility.]]
+}
+
+-- see amp1.lua
+function dsp_ioconfig ()
+ return { [1] = { audio_in = -1, audio_out = -1}, }
+end
+
+function dsp_configure (ins, outs)
+ audio_ins = ins:n_audio();
+ local audio_outs = outs:n_audio()
+ assert (audio_ins == audio_outs)
+end
+
+
+-- this variant modifies the audio data in-place
+-- in Ardour's buffer.
+--
+-- It relies on the fact that by default Ardour requires
+-- plugins to process data in-place (zero copy).
+--
+-- Every assignment directly calls a c-function behind
+-- the scenes to get/set the value.
+-- It's a bit more efficient than "Amp I" on most systems.
+
+function dsp_runmap (bufs, in_map, out_map, n_samples, offset)
+ for c = 1,audio_ins do
+ -- ensure that processing does happen in-place
+ local ib = in_map:get(ARDOUR.DataType("audio"), c - 1); -- get id of mapped input buffer for given cannel
+ local ob = out_map:get(ARDOUR.DataType("audio"), c - 1); -- get id of mapped output buffer for given cannel
+ assert (ib ~= ARDOUR.ChanMapping.Invalid);
+ assert (ob ~= ARDOUR.ChanMapping.Invalid);
+
+ local bi = bufs:get_audio(ib)
+ local bo = bufs:get_audio(ob)
+ assert (bi:sameinstance(bo))
+
+ local a = bufs:get_audio(ib):data(offset):array() -- get a reference (pointer to array)
+ for s = 1,n_samples do
+ a[s] = a[s] * 2; -- modify data in-place (shared with ardour)
+ end
+ end
+end
--- /dev/null
+ardour {
+ ["type"] = "dsp",
+ name = "Simple Amp III",
+ category = "Example",
+ license = "MIT",
+ author = "Ardour Lua Task Force",
+ description = [[
+ An Example DSP Plugin for processing audio, to
+ be used with Ardour's Lua scripting facility.]]
+}
+
+function dsp_ioconfig ()
+ return
+ {
+ { audio_in = -1, audio_out = -1},
+ }
+end
+
+
+function dsp_params ()
+ return
+ {
+ { ["type"] = "input", name = "Gain", min = -20, max = 20, default = 6, unit="dB", scalepoints = { ["0"] = 0, ["twice as loud"] = 6 , ["half as loud"] = -6 } },
+ }
+end
+
+
+-- use ardour's vectorized functions
+--
+-- This is as efficient as Ardour doing it itself in C++
+-- Lua function overhead is negligible
+--
+-- this also exemplifies the /simpler/ way of delegating the
+-- channel-mapping to ardour.
+
+function dsp_run (ins, outs, n_samples)
+ local ctrl = CtrlPorts:array() -- get control port array (read/write)
+ local gain = ARDOUR.DSP.dB_to_coefficient (ctrl[1])
+ assert (#ins == #outs) -- ensure that we can run in-place (channel count matches)
+ for c = 1,#ins do
+ assert (ins[c]:sameinstance(outs[c])) -- check in-place
+ ARDOUR.DSP.apply_gain_to_buffer (ins[c], n_samples, gain); -- process in-place
+ end
+end
--- /dev/null
+ardour {
+ ["type"] = "dsp",
+ name = "Biquad Filter",
+ category = "Filter",
+ license = "MIT",
+ author = "Ardour Lua Task Force",
+ description = [[A Versatile Filter Plugin]]
+}
+
+function dsp_ioconfig ()
+ return
+ {
+ -- allow any number of I/O as long as port-count matches
+ { audio_in = -1, audio_out = -1},
+ }
+end
+
+
+function dsp_params ()
+ return
+ {
+ { ["type"] = "input", name = "Enable", min = 0, max = 1, default = 1, bypass = true, toggled = true },
+ { ["type"] = "input", name = "Type", min = 0, max = 4, default = 0, enum = true, scalepoints =
+ {
+ ["Peaking"] = 0,
+ ["Low Shelf"] = 1,
+ ["High Shelf"] = 2,
+ ["Low Pass"] = 3,
+ ["High Pass"] = 4,
+ }
+ },
+ { ["type"] = "input", name = "Gain", min = -20, max = 20, default = 0, unit="dB" },
+ { ["type"] = "input", name = "Freq", min = 20, max = 20000, default = 1000, unit="Hz", logarithmic = true },
+ { ["type"] = "input", name = "Q", min = 0.1, max = 8, default = .707, logarithmic = true },
+ }
+end
+
+-- translate type parameter to DSP enum
+-- http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR.DSP.Biquad.Type
+function map_type (t)
+ if t == 1 then
+ return ARDOUR.DSP.BiquadType.LowShelf
+ elseif t == 2 then
+ return ARDOUR.DSP.BiquadType.HighShelf
+ elseif t == 3 then
+ return ARDOUR.DSP.BiquadType.LowPass
+ elseif t == 4 then
+ return ARDOUR.DSP.BiquadType.HighPass
+ else
+ return ARDOUR.DSP.BiquadType.Peaking
+ end
+end
+
+function ctrl_data ()
+ local ctrl = CtrlPorts:array ()
+ if ctrl[1] <= 0 then -- when disabled
+ ctrl[3] = 0; -- force gain to 0dB
+ end
+ return ctrl
+end
+
+-- these globals are *not* shared between DSP and UI
+local filters = {} -- the biquad filter instances (DSP)
+local filt -- the biquad filter instance (GUI, response)
+local cur = {0, 0, 0, 0, 0} -- current parameters
+local lpf = 0.03 -- parameter low-pass filter time-constant
+local chn = 0 -- channel/filter count
+
+function dsp_init (rate)
+ self:shmem ():allocate (1) -- shared mem to tell the GUI the samplerate
+ local cfg = self:shmem ():to_int (0):array ()
+ cfg[1] = rate
+ -- http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR:DSP:Biquad
+ filt = ARDOUR.DSP.Biquad (rate) -- initialize filter
+ lpf = 13000 / rate -- interpolation time constant
+end
+
+function dsp_configure (ins, outs)
+ assert (ins:n_audio () == outs:n_audio ())
+ local cfg = self:shmem ():to_int (0):array ()
+ local rate = cfg[1]
+ chn = ins:n_audio ()
+ for c = 1, chn do
+ filters[c] = ARDOUR.DSP.Biquad (rate) -- initialize filters
+ end
+ cur = {0, 0, 0, 0, 0}
+end
+
+-- helper functions for parameter interpolation
+function param_changed (ctrl)
+ if ctrl[2] == cur[2] and ctrl[3] == cur[3] and ctrl[4] == cur[4] and ctrl[5] == cur[5] then
+ return false
+ end
+ return true
+end
+
+function low_pass_filter_param (old, new, limit)
+ if math.abs (old - new) < limit then
+ return new
+ else
+ return old + lpf * (new - old)
+ end
+end
+
+-- apply parameters, re-compute filter coefficients if needed
+function apply_params (ctrl)
+ if not param_changed (ctrl) then
+ return
+ end
+
+ if cur[2] ~= ctrl[2] then
+ -- reset filter state when type changes
+ filt:reset ()
+ for k = 2,5 do cur[k] = ctrl[k] end
+ else
+ -- low-pass filter ctrl parameter values, smooth transition
+ cur[3] = low_pass_filter_param (cur[3], ctrl[3], 0.1) -- gain/dB
+ cur[4] = low_pass_filter_param (cur[4], ctrl[4], 1.0) -- freq/Hz
+ cur[5] = low_pass_filter_param (cur[5], ctrl[5], 0.01) -- quality
+ end
+
+ for c = 1, chn do
+ filters[c]:compute (map_type (cur[2]), cur[4], cur[5], cur[3])
+ end
+end
+
+
+-- the actual DSP callback
+function dsp_run (ins, outs, n_samples)
+ local changed = false
+ local siz = n_samples
+ local off = 0
+ local ctrl = ctrl_data ()
+
+ -- if a parameter was changed, process at most 64 samples at a time
+ -- and interpolate parameters until the current settings match
+ -- the target values
+ if param_changed (ctrl) then
+ changed = true
+ siz = 64
+ end
+
+ while n_samples > 0 do
+ if changed then apply_params (ctrl) end
+ if siz > n_samples then siz = n_samples end
+
+ -- process all channels
+ for c = 1,#ins do
+ -- check if output and input buffers for this channel are identical
+ -- http://manual.ardour.org/lua-scripting/class_reference/#C:FloatArray
+ if ins[c]:sameinstance (outs[c]) then
+ filters[c]:run (ins[c]:offset (off), siz) -- in-place processing
+ else
+ -- http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR:DSP
+ ARDOUR.DSP.copy_vector (outs[c]:offset (off), ins[c]:offset (off), siz)
+ filters[c]:run (outs[c]:offset (off), siz)
+ end
+ end
+
+ n_samples = n_samples - siz
+ off = off + siz
+ end
+
+ if changed then
+ -- notify display
+ self:queue_draw ()
+ end
+end
+
+
+-------------------------------------------------------------------------------
+--- inline display
+
+function round (n)
+ return math.floor (n + .5)
+end
+
+function freq_at_x (x, w)
+ -- x-axis pixel for given freq, power-scale
+ return 20 * 1000 ^ (x / w)
+end
+
+function x_at_freq (f, w)
+ -- frequency at given x-axis pixel
+ return w * math.log (f / 20.0) / math.log (1000.0)
+end
+
+function db_to_y (db, h)
+ -- y-axis gain mapping
+ if db < -20 then db = -20 end
+ if db > 20 then db = 20 end
+ return -.5 + 0.5 * h * (1 - db / 20)
+end
+
+function grid_db (ctx, w, h, db)
+ -- draw horizontal grid line
+ local y = -.5 + round (db_to_y (db, h))
+ ctx:move_to (0, y)
+ ctx:line_to (w, y)
+ ctx:stroke ()
+end
+
+function grid_freq (ctx, w, h, f)
+ -- draw vertical grid line
+ local x = -.5 + round (x_at_freq (f, w))
+ ctx:move_to (x, 0)
+ ctx:line_to (x, h)
+ ctx:stroke ()
+end
+
+function render_inline (ctx, w, max_h)
+ if not filt then
+ -- the GUI is separate from the DSP, but the GUI needs to know
+ -- the sample-rate that the DSP is using.
+ local shmem = self:shmem () -- get shared memory region
+ local cfg = shmem:to_int (0):array () -- "cast" into lua-table
+ -- instantiate filter (to calculate the transfer function's response)
+ filt = ARDOUR.DSP.Biquad (cfg[1])
+ end
+
+ -- set filter coefficients if they have changed
+ if param_changed (CtrlPorts:array ()) then
+ local ctrl = ctrl_data ()
+ for k = 2,5 do cur[k] = ctrl[k] end
+ filt:compute (map_type (cur[2]), cur[4], cur[5], cur[3])
+ end
+
+ -- calc height of inline display
+ local h = math.ceil (w * 10 / 16) -- use 16:10 aspect
+ h = 2 * round (h / 2) -- with an even number of vertical pixels
+ if (h > max_h) then h = max_h end -- but at most max-height
+
+ -- ctx is a http://cairographics.org/ context
+ -- http://manual.ardour.org/lua-scripting/class_reference/#Cairo:Context
+
+ -- clear background
+ ctx:rectangle (0, 0, w, h)
+ ctx:set_source_rgba (.2, .2, .2, 1.0)
+ ctx:fill ()
+
+ -- set line width: 1px
+ -- Note: a cairo pixel at [1,1] spans [0.5->1.5 , 0.5->1.5]
+ -- hence the offset -0.5 in various move_to(), line_to() calls
+ ctx:set_line_width (1.0)
+
+ -- draw grid
+ local dash3 = C.DoubleVector ()
+ dash3:add ({1, 3})
+ ctx:set_dash (dash3, 2) -- dotted line
+ ctx:set_source_rgba (.5, .5, .5, .5)
+ grid_db (ctx, w, h, 0)
+ grid_db (ctx, w, h, 6)
+ grid_db (ctx, w, h, 12)
+ grid_db (ctx, w, h, 18)
+ grid_db (ctx, w, h, -6)
+ grid_db (ctx, w, h, -12)
+ grid_db (ctx, w, h, -18)
+ grid_freq (ctx, w, h, 100)
+ grid_freq (ctx, w, h, 1000)
+ grid_freq (ctx, w, h, 10000)
+ ctx:unset_dash ()
+
+ -- draw transfer function line
+ ctx:set_source_rgba (.8, .8, .8, 1.0)
+ ctx:move_to (-.5, db_to_y (filt:dB_at_freq (freq_at_x (0, w)), h))
+ for x = 1,w do
+ local db = filt:dB_at_freq (freq_at_x (x, w))
+ ctx:line_to (-.5 + x, db_to_y (db, h))
+ end
+ ctx:stroke_preserve ()
+
+ -- fill area to zero under the curve
+ ctx:line_to (w, -.5 + h * .5)
+ ctx:line_to (0, -.5 + h * .5)
+ ctx:close_path ()
+ ctx:set_source_rgba (.5, .5, .5, .5)
+ ctx:fill ()
+
+ return {w, h}
+end
--- /dev/null
+ardour {
+ ["type"] = "EditorHook",
+ name = "Callback Example",
+ author = "Ardour Lua Task Force",
+ description = "Rewind On Solo Change, Write a file when regions are moved",
+}
+
+function signals ()
+ s = LuaSignal.Set()
+ --s:add ({[LuaSignal.SoloActive] = true, [LuaSignal.RegionPropertyChanged] = true})
+ s:add (
+ {
+ [LuaSignal.SoloActive] = true,
+ [LuaSignal.RegionPropertyChanged] = true
+ }
+ )
+ --for k,v in pairs (s:table()) do print (k, v) end
+ return s
+end
+
+function factory (params)
+ return function (signal, ref, ...)
+ print (signal, ref, ...)
+
+ if (signal == LuaSignal.SoloActive) then
+ Session:goto_start()
+ end
+
+ if (signal == LuaSignal.RegionPropertyChanged) then
+ obj,pch = ...
+ file = io.open ("/tmp/test" ,"a")
+ io.output (file)
+ io.write (string.format ("Region: '%s' pos-changed: %s, length-changed: %s\n",
+ obj:name (),
+ tostring (pch:containsFramePos (ARDOUR.Properties.Start)),
+ tostring (pch:containsFramePos (ARDOUR.Properties.Length))
+ ))
+ io.close (file)
+ end
+ end
+end
--- /dev/null
+ardour {
+ ["type"] = "EditorHook",
+ name = "OSC Callback Example",
+ author = "Ardour Lua Task Force",
+ description = "Send OSC messages",
+}
+
+function action_params ()
+ return
+ {
+ ["uri"] = { title = "OSC URI ", default = "osc.udp://localhost:7890"},
+ }
+end
+
+
+function signals ()
+ s = LuaSignal.Set()
+ s:add (
+ {
+ [LuaSignal.SoloActive] = true,
+ [LuaSignal.RegionPropertyChanged] = true,
+ [LuaSignal.Exported] = true,
+ [LuaSignal.TransportStateChange] = true
+ }
+ )
+ return s
+end
+
+function factory (params)
+ return function (signal, ref, ...)
+ local uri = params["unique"] or "osc.udp://localhost:7890"
+ local tx = ARDOUR.LuaOSC.Address (uri)
+ -- debug print (stdout)
+ -- print (signal, ref, ...)
+
+ if (signal == LuaSignal.Exported) then
+ tx:send ("/session/exported", "ss", ...)
+ elseif (signal == LuaSignal.SoloActive) then
+ tx:send ("/session/solo_changed", "")
+ elseif (signal == LuaSignal.TransportStateChange) then
+ tx:send ("/session/transport", "if",
+ Session:transport_frame(), Session:transport_speed())
+ elseif (signal == LuaSignal.RegionPropertyChanged) then
+ obj,pch = ...
+ tx:send ("/region_property_changed", "sTTiii",
+ obj:name (),
+ (pch:containsFramePos (ARDOUR.Properties.Start)),
+ (pch:containsFramePos (ARDOUR.Properties.Length)),
+ obj:position (), obj:start (), obj:length ())
+ end
+ end
+end
--- /dev/null
+ardour {
+ ["type"] = "dsp",
+ name = "Midi Passthru",
+ category = "Example",
+ license = "MIT",
+ author = "Ardour Lua Task Force",
+ description = [[An Example Audio/MIDI Passthrough Plugin using Buffer Pointers]]
+}
+
+-- return possible audio i/o configurations
+function dsp_ioconfig ()
+ -- -1, -1 = any number of channels as long as input and output count matches
+ -- require 1 MIDI in, 1 MIDI out.
+ return { { midi_in = 1, midi_out = 1, audio_in = -1, audio_out = -1}, }
+end
+
+-- "dsp_runmap" uses Ardour's internal processor API, eqivalent to
+-- 'connect_and_run()". There is no overhead (mapping, translating buffers).
+-- The lua implementation is responsible to map all the buffers directly.
+function dsp_runmap (bufs, in_map, out_map, n_samples, offset)
+
+ -- http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR:ChanMapping
+
+ local ib = in_map:get (ARDOUR.DataType ("midi"), 0) -- get index of the 1st mapped midi input buffer
+ assert (ib ~= ARDOUR.ChanMapping.Invalid)
+
+ if ib ~= ARDOUR.ChanMapping.Invalid then
+ -- http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR:MidiBuffer
+ local mb = bufs:get_midi (ib) -- get the mapped buffer
+ local events = mb:table () -- copy event list into a lua table
+
+ -- iterate over all MIDI events
+ for _, e in pairs (events) do
+ -- e is-a http://manual.ardour.org/lua-scripting/class_reference/#Evoral:MidiEvent
+
+ -- do something with the event e.g.
+ print (e:channel (), e:time (), e:size (), e:buffer ():array ()[1], e:buffer ():get_table (e:size ())[1])
+ end
+ end
+
+ ----
+ -- The following code is needed with "dsp_runmap" to work for arbitrary pin connections
+ -- this passes though all audio/midi data unprocessed.
+
+ ARDOUR.DSP.process_map (bufs, in_map, out_map, n_samples, offset, ARDOUR.DataType ("audio"))
+ ARDOUR.DSP.process_map (bufs, in_map, out_map, n_samples, offset, ARDOUR.DataType ("midi"))
+
+ -- equivalent lua code.
+ -- NOTE: the lua implementation below is intended for io-config [-1,-1].
+ -- It only works for actually mapped channels due to in_map:count() out_map:count()
+ -- being identical to the i/o pin count in this case.
+ --
+ -- Plugins that have multiple possible configurations will need to implement
+ -- dsp_configure() and remember the actual channel count.
+ --
+ -- ARDOUR.DSP.process_map() does iterate over the mapping itself and works generally.
+ -- Still the lua code below does lend itself as elaborate example.
+ --
+ --[[
+
+ local audio_ins = in_map:count (): n_audio () -- number of mapped audio input buffers
+ local audio_outs = out_map:count (): n_audio () -- number of mapped audio output buffers
+ assert (audio_outs, audio_ins) -- ioconfig [-1, -1]: must match
+
+ -- copy audio data if any
+ for c = 1, audio_ins do
+ local ib = in_map:get (ARDOUR.DataType ("audio"), c - 1) -- get index of mapped input buffer
+ local ob = out_map:get (ARDOUR.DataType ("audio"), c - 1) -- get index of mapped output buffer
+ if ib ~= ARDOUR.ChanMapping.Invalid and ob ~= ARDOUR.ChanMapping.Invalid and ib ~= ob then
+ -- http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR:DSP
+ -- http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR:AudioBuffer
+ ARDOUR.DSP.copy_vector (bufs:get_audio (ob):data (offset), bufs:get_audio (ib):data (offset), n_samples)
+ end
+ end
+ -- Clear unconnected output buffers.
+ -- In case we're processing in-place some buffers may be identical,
+ -- so this must be done *after* copying relvant data from that port.
+ for c = 1, audio_outs do
+ local ib = in_map:get (ARDOUR.DataType ("audio"), c - 1)
+ local ob = out_map:get (ARDOUR.DataType ("audio"), c - 1)
+ if ib == ARDOUR.ChanMapping.Invalid and ob ~= ARDOUR.ChanMapping.Invalid then
+ bufs:get_audio (ob):silence (n_samples, offset)
+ end
+ end
+
+ -- copy midi data
+ local midi_ins = in_map:count (): n_midi () -- number of midi input buffers
+ local midi_outs = out_map:count (): n_midi () -- number of midi input buffers
+
+ -- with midi_in=1, midi_out=1 in dsp_ioconfig
+ -- the following will always be true
+ assert (midi_ins == 1)
+ assert (midi_outs == 1)
+
+ for c = 1, midi_ins do
+ local ib = in_map:get (ARDOUR.DataType ("midi"), c - 1)
+ local ob = out_map:get (ARDOUR.DataType ("midi"), c - 1)
+ if ib ~= ARDOUR.ChanMapping.Invalid and ob ~= ARDOUR.ChanMapping.Invalid and ib ~= ob then
+ bufs:get_midi (ob):copy (bufs:get_midi (ib))
+ end
+ end
+ -- silence unused midi outputs
+ for c = 1, midi_outs do
+ local ib = in_map:get (ARDOUR.DataType ("midi"), c - 1)
+ local ob = out_map:get (ARDOUR.DataType ("midi"), c - 1)
+ if ib == ARDOUR.ChanMapping.Invalid and ob ~= ARDOUR.ChanMapping.Invalid then
+ bufs:get_midi (ob):silence (n_samples, offset)
+ end
+ end
+ --]]
+end
--- /dev/null
+ardour {
+ ["type"] = "session",
+ name = "Good Night",
+ author = "Ardour Lua Task Force",
+ description = [[
+ Example Ardour Session Script.
+ Session scripts are called at the beginning of every process-callback (before doing any audio processing).
+ This example stops the transport after rolling for a configurable time which can be set when instantiating the script.]]
+}
+
+function sess_params ()
+ return
+ {
+ ["print"] = { title = "Debug Print (yes/no)", default = "no", optional = true },
+ ["time"] = { title = "Timeout (sec)", default = "90", optional = false },
+ }
+end
+
+function factory (params)
+ return function (n_samples)
+ local p = params["print"] or "no"
+ local timeout = params["time"] or 90
+ a = a or 0
+ if p ~= "no" then print (a, n_samples, Session:frame_rate (), Session:transport_rolling ()) end -- debug output (not rt safe)
+ if (not Session:transport_rolling()) then
+ a = 0
+ return
+ end
+ a = a + n_samples
+ if (a > timeout * Session:frame_rate()) then
+ Session:request_transport_speed(0.0, true)
+ end
+ end
+end
--- /dev/null
+ardour {
+ ["type"] = "EditorHook",
+ name = "Varispeed Test - 100ms Callback",
+ author = "Ardour Lua Task Force",
+ description = "An example script that invokes a callback a every 0.1sec and modifies the transport speed",
+}
+
+function signals ()
+ s = LuaSignal.Set()
+ s:add (
+ {
+ [LuaSignal.LuaTimerDS] = true,
+ }
+ )
+ return s
+end
+
+function factory (params)
+ -- upindex variables
+ local cnt = 0
+ local speed = 0
+ local delta = 0.01
+ return function (signal, ref, ...)
+ cnt = (cnt + 1) % 5 -- divide clock: every half a second
+ if cnt == 0 then
+ if speed < -0.25 then delta = delta * -1 end
+ if speed > 0.25 then delta = delta * -1 end
+ speed = speed + delta
+ Session:request_transport_speed (speed)
+ end
+ end
+end
+++ /dev/null
-ardour {
- ["type"] = "dsp",
- name = "Simple Amp",
- category = "Example",
- license = "MIT",
- author = "Ardour Lua Task Force",
- description = [[
- An Example DSP Plugin for processing audio, to
- be used with Ardour's Lua scripting facility.]]
-}
-
-
--- return possible i/o configurations
-function dsp_ioconfig ()
- -- -1, -1 = any number of channels as long as input and output count matches
- return { [1] = { audio_in = -1, audio_out = -1}, }
-end
-
--- optional function, called when configuring the plugin
-function dsp_configure (ins, outs)
- -- store configuration in global variable
- audio_ins = ins:n_audio();
- local audio_outs = outs:n_audio()
- assert (audio_ins == audio_outs)
-end
-
--- this variant asks for a complete *copy* of the
--- audio data in a lua-table.
--- after processing the data is copied back.
---
--- this also exemplifies the direct "connect and run" process function,
--- where the channel-mapping needs to be done in lua.
-
-function dsp_runmap (bufs, in_map, out_map, n_samples, offset)
- for c = 1,audio_ins do
- -- Note: lua starts counting at 1, ardour's ChanMapping::get() at 0
- local ib = in_map:get(ARDOUR.DataType("audio"), c - 1); -- get id of mapped input buffer for given channel
- local ob = out_map:get(ARDOUR.DataType("audio"), c - 1); -- get id of mapped output buffer for given channel
- assert (ib ~= ARDOUR.ChanMapping.Invalid);
- assert (ob ~= ARDOUR.ChanMapping.Invalid);
- local a = bufs:get_audio (ib):data (offset):get_table(n_samples) -- copy audio-data from input buffer
- for s = 1,n_samples do
- a[s] = a[s] * 2; -- amplify data in lua table
- end
- bufs:get_audio(ob):data(offset):set_table(a, n_samples) -- copy back
- end
-end
+++ /dev/null
-ardour {
- ["type"] = "dsp",
- name = "Simple Amp II",
- category = "Example",
- license = "MIT",
- author = "Ardour Lua Task Force",
- description = [[
- An Example DSP Plugin for processing audio, to
- be used with Ardour's Lua scripting facility.]]
-}
-
--- see amp1.lua
-function dsp_ioconfig ()
- return { [1] = { audio_in = -1, audio_out = -1}, }
-end
-
-function dsp_configure (ins, outs)
- audio_ins = ins:n_audio();
- local audio_outs = outs:n_audio()
- assert (audio_ins == audio_outs)
-end
-
-
--- this variant modifies the audio data in-place
--- in Ardour's buffer.
---
--- It relies on the fact that by default Ardour requires
--- plugins to process data in-place (zero copy).
---
--- Every assignment directly calls a c-function behind
--- the scenes to get/set the value.
--- It's a bit more efficient than "Amp I" on most systems.
-
-function dsp_runmap (bufs, in_map, out_map, n_samples, offset)
- for c = 1,audio_ins do
- -- ensure that processing does happen in-place
- local ib = in_map:get(ARDOUR.DataType("audio"), c - 1); -- get id of mapped input buffer for given cannel
- local ob = out_map:get(ARDOUR.DataType("audio"), c - 1); -- get id of mapped output buffer for given cannel
- assert (ib ~= ARDOUR.ChanMapping.Invalid);
- assert (ob ~= ARDOUR.ChanMapping.Invalid);
-
- local bi = bufs:get_audio(ib)
- local bo = bufs:get_audio(ob)
- assert (bi:sameinstance(bo))
-
- local a = bufs:get_audio(ib):data(offset):array() -- get a reference (pointer to array)
- for s = 1,n_samples do
- a[s] = a[s] * 2; -- modify data in-place (shared with ardour)
- end
- end
-end
+++ /dev/null
-ardour {
- ["type"] = "dsp",
- name = "Simple Amp III",
- category = "Example",
- license = "MIT",
- author = "Ardour Lua Task Force",
- description = [[
- An Example DSP Plugin for processing audio, to
- be used with Ardour's Lua scripting facility.]]
-}
-
-function dsp_ioconfig ()
- return
- {
- { audio_in = -1, audio_out = -1},
- }
-end
-
-
-function dsp_params ()
- return
- {
- { ["type"] = "input", name = "Gain", min = -20, max = 20, default = 6, unit="dB", scalepoints = { ["0"] = 0, ["twice as loud"] = 6 , ["half as loud"] = -6 } },
- }
-end
-
-
--- use ardour's vectorized functions
---
--- This is as efficient as Ardour doing it itself in C++
--- Lua function overhead is negligible
---
--- this also exemplifies the /simpler/ way of delegating the
--- channel-mapping to ardour.
-
-function dsp_run (ins, outs, n_samples)
- local ctrl = CtrlPorts:array() -- get control port array (read/write)
- local gain = ARDOUR.DSP.dB_to_coefficient (ctrl[1])
- assert (#ins == #outs) -- ensure that we can run in-place (channel count matches)
- for c = 1,#ins do
- assert (ins[c]:sameinstance(outs[c])) -- check in-place
- ARDOUR.DSP.apply_gain_to_buffer (ins[c], n_samples, gain); -- process in-place
- end
-end
+++ /dev/null
-ardour {
- ["type"] = "dsp",
- name = "Biquad Filter",
- category = "Filter",
- license = "MIT",
- author = "Ardour Lua Task Force",
- description = [[A Versatile Filter Plugin]]
-}
-
-function dsp_ioconfig ()
- return
- {
- -- allow any number of I/O as long as port-count matches
- { audio_in = -1, audio_out = -1},
- }
-end
-
-
-function dsp_params ()
- return
- {
- { ["type"] = "input", name = "Enable", min = 0, max = 1, default = 1, bypass = true, toggled = true },
- { ["type"] = "input", name = "Type", min = 0, max = 4, default = 0, enum = true, scalepoints =
- {
- ["Peaking"] = 0,
- ["Low Shelf"] = 1,
- ["High Shelf"] = 2,
- ["Low Pass"] = 3,
- ["High Pass"] = 4,
- }
- },
- { ["type"] = "input", name = "Gain", min = -20, max = 20, default = 0, unit="dB" },
- { ["type"] = "input", name = "Freq", min = 20, max = 20000, default = 1000, unit="Hz", logarithmic = true },
- { ["type"] = "input", name = "Q", min = 0.1, max = 8, default = .707, logarithmic = true },
- }
-end
-
--- translate type parameter to DSP enum
--- http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR.DSP.Biquad.Type
-function map_type (t)
- if t == 1 then
- return ARDOUR.DSP.BiquadType.LowShelf
- elseif t == 2 then
- return ARDOUR.DSP.BiquadType.HighShelf
- elseif t == 3 then
- return ARDOUR.DSP.BiquadType.LowPass
- elseif t == 4 then
- return ARDOUR.DSP.BiquadType.HighPass
- else
- return ARDOUR.DSP.BiquadType.Peaking
- end
-end
-
-function ctrl_data ()
- local ctrl = CtrlPorts:array ()
- if ctrl[1] <= 0 then -- when disabled
- ctrl[3] = 0; -- force gain to 0dB
- end
- return ctrl
-end
-
--- these globals are *not* shared between DSP and UI
-local filters = {} -- the biquad filter instances (DSP)
-local filt -- the biquad filter instance (GUI, response)
-local cur = {0, 0, 0, 0, 0} -- current parameters
-local lpf = 0.03 -- parameter low-pass filter time-constant
-local chn = 0 -- channel/filter count
-
-function dsp_init (rate)
- self:shmem ():allocate (1) -- shared mem to tell the GUI the samplerate
- local cfg = self:shmem ():to_int (0):array ()
- cfg[1] = rate
- -- http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR:DSP:Biquad
- filt = ARDOUR.DSP.Biquad (rate) -- initialize filter
- lpf = 13000 / rate -- interpolation time constant
-end
-
-function dsp_configure (ins, outs)
- assert (ins:n_audio () == outs:n_audio ())
- local cfg = self:shmem ():to_int (0):array ()
- local rate = cfg[1]
- chn = ins:n_audio ()
- for c = 1, chn do
- filters[c] = ARDOUR.DSP.Biquad (rate) -- initialize filters
- end
- cur = {0, 0, 0, 0, 0}
-end
-
--- helper functions for parameter interpolation
-function param_changed (ctrl)
- if ctrl[2] == cur[2] and ctrl[3] == cur[3] and ctrl[4] == cur[4] and ctrl[5] == cur[5] then
- return false
- end
- return true
-end
-
-function low_pass_filter_param (old, new, limit)
- if math.abs (old - new) < limit then
- return new
- else
- return old + lpf * (new - old)
- end
-end
-
--- apply parameters, re-compute filter coefficients if needed
-function apply_params (ctrl)
- if not param_changed (ctrl) then
- return
- end
-
- if cur[2] ~= ctrl[2] then
- -- reset filter state when type changes
- filt:reset ()
- for k = 2,5 do cur[k] = ctrl[k] end
- else
- -- low-pass filter ctrl parameter values, smooth transition
- cur[3] = low_pass_filter_param (cur[3], ctrl[3], 0.1) -- gain/dB
- cur[4] = low_pass_filter_param (cur[4], ctrl[4], 1.0) -- freq/Hz
- cur[5] = low_pass_filter_param (cur[5], ctrl[5], 0.01) -- quality
- end
-
- for c = 1, chn do
- filters[c]:compute (map_type (cur[2]), cur[4], cur[5], cur[3])
- end
-end
-
-
--- the actual DSP callback
-function dsp_run (ins, outs, n_samples)
- local changed = false
- local siz = n_samples
- local off = 0
- local ctrl = ctrl_data ()
-
- -- if a parameter was changed, process at most 64 samples at a time
- -- and interpolate parameters until the current settings match
- -- the target values
- if param_changed (ctrl) then
- changed = true
- siz = 64
- end
-
- while n_samples > 0 do
- if changed then apply_params (ctrl) end
- if siz > n_samples then siz = n_samples end
-
- -- process all channels
- for c = 1,#ins do
- -- check if output and input buffers for this channel are identical
- -- http://manual.ardour.org/lua-scripting/class_reference/#C:FloatArray
- if ins[c]:sameinstance (outs[c]) then
- filters[c]:run (ins[c]:offset (off), siz) -- in-place processing
- else
- -- http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR:DSP
- ARDOUR.DSP.copy_vector (outs[c]:offset (off), ins[c]:offset (off), siz)
- filters[c]:run (outs[c]:offset (off), siz)
- end
- end
-
- n_samples = n_samples - siz
- off = off + siz
- end
-
- if changed then
- -- notify display
- self:queue_draw ()
- end
-end
-
-
--------------------------------------------------------------------------------
---- inline display
-
-function round (n)
- return math.floor (n + .5)
-end
-
-function freq_at_x (x, w)
- -- x-axis pixel for given freq, power-scale
- return 20 * 1000 ^ (x / w)
-end
-
-function x_at_freq (f, w)
- -- frequency at given x-axis pixel
- return w * math.log (f / 20.0) / math.log (1000.0)
-end
-
-function db_to_y (db, h)
- -- y-axis gain mapping
- if db < -20 then db = -20 end
- if db > 20 then db = 20 end
- return -.5 + 0.5 * h * (1 - db / 20)
-end
-
-function grid_db (ctx, w, h, db)
- -- draw horizontal grid line
- local y = -.5 + round (db_to_y (db, h))
- ctx:move_to (0, y)
- ctx:line_to (w, y)
- ctx:stroke ()
-end
-
-function grid_freq (ctx, w, h, f)
- -- draw vertical grid line
- local x = -.5 + round (x_at_freq (f, w))
- ctx:move_to (x, 0)
- ctx:line_to (x, h)
- ctx:stroke ()
-end
-
-function render_inline (ctx, w, max_h)
- if not filt then
- -- the GUI is separate from the DSP, but the GUI needs to know
- -- the sample-rate that the DSP is using.
- local shmem = self:shmem () -- get shared memory region
- local cfg = shmem:to_int (0):array () -- "cast" into lua-table
- -- instantiate filter (to calculate the transfer function's response)
- filt = ARDOUR.DSP.Biquad (cfg[1])
- end
-
- -- set filter coefficients if they have changed
- if param_changed (CtrlPorts:array ()) then
- local ctrl = ctrl_data ()
- for k = 2,5 do cur[k] = ctrl[k] end
- filt:compute (map_type (cur[2]), cur[4], cur[5], cur[3])
- end
-
- -- calc height of inline display
- local h = math.ceil (w * 10 / 16) -- use 16:10 aspect
- h = 2 * round (h / 2) -- with an even number of vertical pixels
- if (h > max_h) then h = max_h end -- but at most max-height
-
- -- ctx is a http://cairographics.org/ context
- -- http://manual.ardour.org/lua-scripting/class_reference/#Cairo:Context
-
- -- clear background
- ctx:rectangle (0, 0, w, h)
- ctx:set_source_rgba (.2, .2, .2, 1.0)
- ctx:fill ()
-
- -- set line width: 1px
- -- Note: a cairo pixel at [1,1] spans [0.5->1.5 , 0.5->1.5]
- -- hence the offset -0.5 in various move_to(), line_to() calls
- ctx:set_line_width (1.0)
-
- -- draw grid
- local dash3 = C.DoubleVector ()
- dash3:add ({1, 3})
- ctx:set_dash (dash3, 2) -- dotted line
- ctx:set_source_rgba (.5, .5, .5, .5)
- grid_db (ctx, w, h, 0)
- grid_db (ctx, w, h, 6)
- grid_db (ctx, w, h, 12)
- grid_db (ctx, w, h, 18)
- grid_db (ctx, w, h, -6)
- grid_db (ctx, w, h, -12)
- grid_db (ctx, w, h, -18)
- grid_freq (ctx, w, h, 100)
- grid_freq (ctx, w, h, 1000)
- grid_freq (ctx, w, h, 10000)
- ctx:unset_dash ()
-
- -- draw transfer function line
- ctx:set_source_rgba (.8, .8, .8, 1.0)
- ctx:move_to (-.5, db_to_y (filt:dB_at_freq (freq_at_x (0, w)), h))
- for x = 1,w do
- local db = filt:dB_at_freq (freq_at_x (x, w))
- ctx:line_to (-.5 + x, db_to_y (db, h))
- end
- ctx:stroke_preserve ()
-
- -- fill area to zero under the curve
- ctx:line_to (w, -.5 + h * .5)
- ctx:line_to (0, -.5 + h * .5)
- ctx:close_path ()
- ctx:set_source_rgba (.5, .5, .5, .5)
- ctx:fill ()
-
- return {w, h}
-end
+++ /dev/null
-ardour {
- ["type"] = "EditorHook",
- name = "Callback Example",
- author = "Ardour Lua Task Force",
- description = "Rewind On Solo Change, Write a file when regions are moved",
-}
-
-function signals ()
- s = LuaSignal.Set()
- --s:add ({[LuaSignal.SoloActive] = true, [LuaSignal.RegionPropertyChanged] = true})
- s:add (
- {
- [LuaSignal.SoloActive] = true,
- [LuaSignal.RegionPropertyChanged] = true
- }
- )
- --for k,v in pairs (s:table()) do print (k, v) end
- return s
-end
-
-function factory (params)
- return function (signal, ref, ...)
- print (signal, ref, ...)
-
- if (signal == LuaSignal.SoloActive) then
- Session:goto_start()
- end
-
- if (signal == LuaSignal.RegionPropertyChanged) then
- obj,pch = ...
- file = io.open ("/tmp/test" ,"a")
- io.output (file)
- io.write (string.format ("Region: '%s' pos-changed: %s, length-changed: %s\n",
- obj:name (),
- tostring (pch:containsFramePos (ARDOUR.Properties.Start)),
- tostring (pch:containsFramePos (ARDOUR.Properties.Length))
- ))
- io.close (file)
- end
- end
-end
+++ /dev/null
-ardour {
- ["type"] = "EditorHook",
- name = "OSC Callback Example",
- author = "Ardour Lua Task Force",
- description = "Send OSC messages",
-}
-
-function action_params ()
- return
- {
- ["uri"] = { title = "OSC URI ", default = "osc.udp://localhost:7890"},
- }
-end
-
-
-function signals ()
- s = LuaSignal.Set()
- s:add (
- {
- [LuaSignal.SoloActive] = true,
- [LuaSignal.RegionPropertyChanged] = true,
- [LuaSignal.Exported] = true,
- [LuaSignal.TransportStateChange] = true
- }
- )
- return s
-end
-
-function factory (params)
- return function (signal, ref, ...)
- local uri = params["unique"] or "osc.udp://localhost:7890"
- local tx = ARDOUR.LuaOSC.Address (uri)
- -- debug print (stdout)
- -- print (signal, ref, ...)
-
- if (signal == LuaSignal.Exported) then
- tx:send ("/session/exported", "ss", ...)
- elseif (signal == LuaSignal.SoloActive) then
- tx:send ("/session/solo_changed", "")
- elseif (signal == LuaSignal.TransportStateChange) then
- tx:send ("/session/transport", "if",
- Session:transport_frame(), Session:transport_speed())
- elseif (signal == LuaSignal.RegionPropertyChanged) then
- obj,pch = ...
- tx:send ("/region_property_changed", "sTTiii",
- obj:name (),
- (pch:containsFramePos (ARDOUR.Properties.Start)),
- (pch:containsFramePos (ARDOUR.Properties.Length)),
- obj:position (), obj:start (), obj:length ())
- end
- end
-end
+++ /dev/null
-ardour {
- ["type"] = "dsp",
- name = "Midi Passthru",
- category = "Example",
- license = "MIT",
- author = "Ardour Lua Task Force",
- description = [[An Example Audio/MIDI Passthrough Plugin using Buffer Pointers]]
-}
-
--- return possible audio i/o configurations
-function dsp_ioconfig ()
- -- -1, -1 = any number of channels as long as input and output count matches
- -- require 1 MIDI in, 1 MIDI out.
- return { { midi_in = 1, midi_out = 1, audio_in = -1, audio_out = -1}, }
-end
-
--- "dsp_runmap" uses Ardour's internal processor API, eqivalent to
--- 'connect_and_run()". There is no overhead (mapping, translating buffers).
--- The lua implementation is responsible to map all the buffers directly.
-function dsp_runmap (bufs, in_map, out_map, n_samples, offset)
-
- -- http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR:ChanMapping
-
- local ib = in_map:get (ARDOUR.DataType ("midi"), 0) -- get index of the 1st mapped midi input buffer
- assert (ib ~= ARDOUR.ChanMapping.Invalid)
-
- if ib ~= ARDOUR.ChanMapping.Invalid then
- -- http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR:MidiBuffer
- local mb = bufs:get_midi (ib) -- get the mapped buffer
- local events = mb:table () -- copy event list into a lua table
-
- -- iterate over all MIDI events
- for _, e in pairs (events) do
- -- e is-a http://manual.ardour.org/lua-scripting/class_reference/#Evoral:MidiEvent
-
- -- do something with the event e.g.
- print (e:channel (), e:time (), e:size (), e:buffer ():array ()[1], e:buffer ():get_table (e:size ())[1])
- end
- end
-
- ----
- -- The following code is needed with "dsp_runmap" to work for arbitrary pin connections
- -- this passes though all audio/midi data unprocessed.
-
- ARDOUR.DSP.process_map (bufs, in_map, out_map, n_samples, offset, ARDOUR.DataType ("audio"))
- ARDOUR.DSP.process_map (bufs, in_map, out_map, n_samples, offset, ARDOUR.DataType ("midi"))
-
- -- equivalent lua code.
- -- NOTE: the lua implementation below is intended for io-config [-1,-1].
- -- It only works for actually mapped channels due to in_map:count() out_map:count()
- -- being identical to the i/o pin count in this case.
- --
- -- Plugins that have multiple possible configurations will need to implement
- -- dsp_configure() and remember the actual channel count.
- --
- -- ARDOUR.DSP.process_map() does iterate over the mapping itself and works generally.
- -- Still the lua code below does lend itself as elaborate example.
- --
- --[[
-
- local audio_ins = in_map:count (): n_audio () -- number of mapped audio input buffers
- local audio_outs = out_map:count (): n_audio () -- number of mapped audio output buffers
- assert (audio_outs, audio_ins) -- ioconfig [-1, -1]: must match
-
- -- copy audio data if any
- for c = 1, audio_ins do
- local ib = in_map:get (ARDOUR.DataType ("audio"), c - 1) -- get index of mapped input buffer
- local ob = out_map:get (ARDOUR.DataType ("audio"), c - 1) -- get index of mapped output buffer
- if ib ~= ARDOUR.ChanMapping.Invalid and ob ~= ARDOUR.ChanMapping.Invalid and ib ~= ob then
- -- http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR:DSP
- -- http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR:AudioBuffer
- ARDOUR.DSP.copy_vector (bufs:get_audio (ob):data (offset), bufs:get_audio (ib):data (offset), n_samples)
- end
- end
- -- Clear unconnected output buffers.
- -- In case we're processing in-place some buffers may be identical,
- -- so this must be done *after* copying relvant data from that port.
- for c = 1, audio_outs do
- local ib = in_map:get (ARDOUR.DataType ("audio"), c - 1)
- local ob = out_map:get (ARDOUR.DataType ("audio"), c - 1)
- if ib == ARDOUR.ChanMapping.Invalid and ob ~= ARDOUR.ChanMapping.Invalid then
- bufs:get_audio (ob):silence (n_samples, offset)
- end
- end
-
- -- copy midi data
- local midi_ins = in_map:count (): n_midi () -- number of midi input buffers
- local midi_outs = out_map:count (): n_midi () -- number of midi input buffers
-
- -- with midi_in=1, midi_out=1 in dsp_ioconfig
- -- the following will always be true
- assert (midi_ins == 1)
- assert (midi_outs == 1)
-
- for c = 1, midi_ins do
- local ib = in_map:get (ARDOUR.DataType ("midi"), c - 1)
- local ob = out_map:get (ARDOUR.DataType ("midi"), c - 1)
- if ib ~= ARDOUR.ChanMapping.Invalid and ob ~= ARDOUR.ChanMapping.Invalid and ib ~= ob then
- bufs:get_midi (ob):copy (bufs:get_midi (ib))
- end
- end
- -- silence unused midi outputs
- for c = 1, midi_outs do
- local ib = in_map:get (ARDOUR.DataType ("midi"), c - 1)
- local ob = out_map:get (ARDOUR.DataType ("midi"), c - 1)
- if ib == ARDOUR.ChanMapping.Invalid and ob ~= ARDOUR.ChanMapping.Invalid then
- bufs:get_midi (ob):silence (n_samples, offset)
- end
- end
- --]]
-end
+++ /dev/null
-ardour {
- ["type"] = "session",
- name = "Good Night",
- author = "Ardour Lua Task Force",
- description = [[
- Example Ardour Session Script.
- Session scripts are called at the beginning of every process-callback (before doing any audio processing).
- This example stops the transport after rolling for a configurable time which can be set when instantiating the script.]]
-}
-
-function sess_params ()
- return
- {
- ["print"] = { title = "Debug Print (yes/no)", default = "no", optional = true },
- ["time"] = { title = "Timeout (sec)", default = "90", optional = false },
- }
-end
-
-function factory (params)
- return function (n_samples)
- local p = params["print"] or "no"
- local timeout = params["time"] or 90
- a = a or 0
- if p ~= "no" then print (a, n_samples, Session:frame_rate (), Session:transport_rolling ()) end -- debug output (not rt safe)
- if (not Session:transport_rolling()) then
- a = 0
- return
- end
- a = a + n_samples
- if (a > timeout * Session:frame_rate()) then
- Session:request_transport_speed(0.0, true)
- end
- end
-end
+++ /dev/null
-ardour {
- ["type"] = "EditorHook",
- name = "Varispeed Test - 100ms Callback",
- author = "Ardour Lua Task Force",
- description = "An example script that invokes a callback a every 0.1sec and modifies the transport speed",
-}
-
-function signals ()
- s = LuaSignal.Set()
- s:add (
- {
- [LuaSignal.LuaTimerDS] = true,
- }
- )
- return s
-end
-
-function factory (params)
- -- upindex variables
- local cnt = 0
- local speed = 0
- local delta = 0.01
- return function (signal, ref, ...)
- cnt = (cnt + 1) % 5 -- divide clock: every half a second
- if cnt == 0 then
- if speed < -0.25 then delta = delta * -1 end
- if speed > 0.25 then delta = delta * -1 end
- speed = speed + delta
- Session:request_transport_speed (speed)
- end
- end
-end
pass
def build(bld):
- scripts = bld.path.ant_glob ('*.lua')
+ scripts = bld.path.ant_glob ('*.lua', excl=['^_*'])
+ print scripts
bld.install_files (os.path.join(bld.env['DATADIR'], 'scripts'), scripts)
def options(opt):