Add API to tap signal from a Delivery to RTA

Rater than having each Delivery Object provide a Ringbuffer,
which is unused most of the time, the GUI will provide
them on demand.

We need to be careful of lifetime, and use `rt_safe_delete` in
case the Delivery holds the last instance.
This commit is contained in:
Robin Gareus
2025-03-25 03:02:06 +01:00
parent 76ba840be0
commit e12d8b3769
2 changed files with 53 additions and 2 deletions

View File

@@ -24,6 +24,8 @@
#include <string>
#include "pbd/ringbuffer.h"
#include "ardour/libardour_visibility.h"
#include "ardour/types.h"
#include "ardour/chan_count.h"
@@ -110,6 +112,17 @@ public:
void set_gain_control (std::shared_ptr<GainControl> gc);
using RTARingBuffer = PBD::RingBuffer<ARDOUR::Sample>;
using RTARingBufferPtr = std::shared_ptr<RTARingBuffer>;
using RTABufferList = std::vector<RTARingBufferPtr>;
using RTABufferListPtr = std::shared_ptr<RTABufferList>;
void set_analysis_buffers (RTABufferListPtr rb) {
_rtabuffers = rb;
}
bool analysis_active () const;
void set_analysis_active (bool);
void set_polarity_control (std::shared_ptr<AutomationControl> ac) {
_polarity_control = ac;
}
@@ -152,6 +165,9 @@ private:
std::shared_ptr<GainControl> _gain_control;
std::shared_ptr<AutomationControl> _polarity_control;
RTABufferListPtr _rtabuffers;
std::atomic<bool> _rta_active;
static bool panners_legal;
static PBD::Signal<void()> PannersLegal;
@@ -164,5 +180,3 @@ private:
} // namespace ARDOUR

View File

@@ -63,6 +63,7 @@ Delivery::Delivery (Session& s, std::shared_ptr<IO> io, std::shared_ptr<Pannable
, _current_gain (GAIN_COEFF_ZERO)
, _no_outs_cuz_we_no_monitor (false)
, _mute_master (mm)
, _rta_active (false)
, _no_panner_reset (false)
{
if (pannable) {
@@ -87,6 +88,7 @@ Delivery::Delivery (Session& s, std::shared_ptr<Pannable> pannable, std::shared_
, _current_gain (GAIN_COEFF_ZERO)
, _no_outs_cuz_we_no_monitor (false)
, _mute_master (mm)
, _rta_active (false)
, _no_panner_reset (false)
{
if (pannable) {
@@ -199,6 +201,19 @@ Delivery::set_gain_control (std::shared_ptr<GainControl> gc) {
}
}
bool
Delivery::analysis_active () const
{
return _rta_active.load ();
}
void
Delivery::set_analysis_active (bool en)
{
// TODO latch with session wide enable, sync'ed at process start
_rta_active.store (en);
}
/** Caller must hold process lock */
bool
Delivery::configure_io (ChanCount in, ChanCount out)
@@ -299,6 +314,14 @@ Delivery::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample
bufs.set_count (output_buffers().count ());
Amp::apply_simple_gain (bufs, nframes, GAIN_COEFF_ZERO);
}
RTABufferListPtr rtabuffers = _rtabuffers;
if (_rta_active.load () && rtabuffers && !rtabuffers->empty ()) {
BufferSet& silent_bufs = _session.get_silent_buffers(ChanCount(DataType::AUDIO, 1));
for (auto const& rb : *rtabuffers) {
rb->write (silent_bufs.get_audio(0).data(), nframes);
}
}
return;
} else if (tgain != GAIN_COEFF_UNITY) {
@@ -320,6 +343,20 @@ Delivery::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample
_amp->run (bufs, start_sample, end_sample, speed, nframes, true);
}
RTABufferListPtr rtabuffers = _rtabuffers;
if (_rta_active.load () && rtabuffers && !rtabuffers->empty ()) {
uint32_t n_audio = bufs.count().n_audio();
uint32_t n = 0;
for (auto const& rb: *rtabuffers) {
if (n < n_audio) {
rb->write (bufs.get_audio (n++).data(), nframes);
} else {
BufferSet& silent_bufs = _session.get_silent_buffers(ChanCount(DataType::AUDIO, 1));
rb->write (silent_bufs.get_audio(0).data(), nframes);
}
}
}
// Panning
if (_panshell && !_panshell->bypassed() && _panshell->panner()) {