From 34789ff22f7a175a7c5214f2d80c0ea33531205d Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Sun, 18 Jun 2023 22:39:45 +0200 Subject: [PATCH] LuaProc: add option to set time information --- libs/ardour/ardour/luaproc.h | 1 + libs/ardour/luaproc.cc | 63 +++++++++++++++++++++++++++++++++++- share/scripts/_time_info.lua | 44 +++++++++++++++++++++++++ 3 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 share/scripts/_time_info.lua diff --git a/libs/ardour/ardour/luaproc.h b/libs/ardour/ardour/luaproc.h index c6efacdb5f..9e83a5de7d 100644 --- a/libs/ardour/ardour/luaproc.h +++ b/libs/ardour/ardour/luaproc.h @@ -157,6 +157,7 @@ private: bool _lua_does_channelmapping; bool _lua_has_inline_display; bool _connect_all_audio_outputs; + bool _set_time_info; void queue_draw () { QueueDraw(); /* EMIT SIGNAL */ } DSP::DspShm lshm; diff --git a/libs/ardour/luaproc.cc b/libs/ardour/luaproc.cc index c8865016e2..0b84686ffe 100644 --- a/libs/ardour/luaproc.cc +++ b/libs/ardour/luaproc.cc @@ -61,6 +61,7 @@ LuaProc::LuaProc (AudioEngine& engine, , _lua_does_channelmapping (false) , _lua_has_inline_display (false) , _connect_all_audio_outputs (false) + , _set_time_info (false) , _designated_bypass_port (UINT32_MAX) , _signal_latency (0) , _control_data (0) @@ -286,6 +287,26 @@ LuaProc::load_script () } } + /* parse options */ + luabridge::LuaRef options = luabridge::getGlobal (L, "dsp_options"); + if (options.isFunction ()) { + try { + luabridge::LuaRef opts = options (); + if (opts.isTable ()) { + for (luabridge::Iterator i (opts); !i.isNil (); ++i) { + if (!i.key().isString()) { + continue; + } + if (i.key().cast () == "time_info" && i.value().isBoolean ()) { + _set_time_info = i.value().cast (); + } + } + } + } catch (...) { + return true; + } + } + // initialize the DSP if needed luabridge::LuaRef lua_dsp_init = luabridge::getGlobal (L, "dsp_init"); if (lua_dsp_init.type () == LUA_TFUNCTION) { @@ -678,6 +699,47 @@ LuaProc::connect_and_run (BufferSet& bufs, #endif try { + lua_State* L = lua.getState (); + + if (_set_time_info) { + using namespace Temporal; + TempoMap::SharedPtr tmap (TempoMap::use ()); + const TempoMetric& metric (tmap->metric_at (timepos_t (start))); + const TempoMetric& metric_end (tmap->metric_at (timepos_t (end))); + const BBT_Time& bbt (metric.bbt_at (timepos_t (start))); + + luabridge::LuaRef lua_time (luabridge::newTable (L)); + + lua_time["sampleTime"] = start; + lua_time["sampleTimeEnd"] = end; + + lua_time["tempo"] = metric.tempo ().quarter_notes_per_minute (); + lua_time["tempoEnd"] = metric_end.tempo ().quarter_notes_per_minute (); + lua_time["musicTime"] = DoubleableBeats (metric.tempo ().quarters_at_sample (start)).to_double (); + lua_time["musicTimeEnd"] = DoubleableBeats (metric_end.tempo ().quarters_at_sample (end)).to_double (); + + lua_time["barPositionMusic"] = bbt.bars * 4; + lua_time["timeSigNumerator"] = metric.meter ().divisions_per_bar (); + lua_time["timeSigDenominator"] = metric.meter ().note_value (); + + lua_time["TCframesPerSecond"] = _session.timecode_frames_per_second (); + lua_time["TCdropFrames"] = _session.timecode_drop_frames (); + + if (_session.get_play_loop ()) { + Location* looploc = _session.locations ()->auto_loop_location (); + lua_time["looping"] = true; + lua_time["loopStart"] = looploc->start ().samples (); + lua_time["loopEnd"] = looploc->end ().samples (); + lua_time["loopStartMusic"] = DoubleableBeats (tmap->quarters_at (looploc->start ())).to_double (); + lua_time["loopEndMusic"] = DoubleableBeats (tmap->quarters_at (looploc->end ())).to_double (); + } else { + lua_time["looping"] = false; + } + + luabridge::push (L, lua_time); + lua_setglobal (L, "time"); + } + if (_lua_does_channelmapping) { // run the DSP function (*_lua_dsp)(&bufs, &in, &out, nframes, offset); @@ -686,7 +748,6 @@ LuaProc::connect_and_run (BufferSet& bufs, BufferSet& silent_bufs = _session.get_silent_buffers (ChanCount (DataType::AUDIO, 1)); BufferSet& scratch_bufs = _session.get_scratch_buffers (ChanCount (DataType::AUDIO, 1)); - lua_State* L = lua.getState (); luabridge::LuaRef in_map (luabridge::newTable (L)); luabridge::LuaRef out_map (luabridge::newTable (L)); diff --git a/share/scripts/_time_info.lua b/share/scripts/_time_info.lua new file mode 100644 index 0000000000..a882f9e9ae --- /dev/null +++ b/share/scripts/_time_info.lua @@ -0,0 +1,44 @@ +ardour { + ["type"] = "dsp", + name = "Time Info", + category = "Utility", + author = "Ardour Team", + license = "MIT", + description = [[Example to use processing time info]] +} + +function dsp_ioconfig () + return { { midi_in = 1, midi_out = 1, audio_in = -1, audio_out = -1}, } +end + +function dsp_options () + return { time_info = true } +end + +function dsp_run (_, _, n_samples) + assert (type(midiout) == "table") + assert (type(time) == "table") + assert (type(midiout) == "table") + local cnt = 1; + + function tx_midi (time, data) + midiout[cnt] = {} + midiout[cnt]["time"] = time; + midiout[cnt]["data"] = data; + cnt = cnt + 1; + end + + -- printing from rt-context is not thread-safe + print ("---") + for k,v in pairs (time) do + print (k, v); + end + + -- pass-thru MIDI + for _,b in pairs (midiin) do + local t = b["time"] -- t = [ 1 .. n_samples ] + local d = b["data"] -- midi-event data + tx_midi (t, d) + end + +end