Refactor input port monitoring

* avoid memory allocation (remove std:set<>&)
* skip nested loop using port-names as IDs

However this adds a bit of extra cost in case input ports are
monitored: get_port_by_name() and get_buffer()
This commit is contained in:
Robin Gareus 2021-06-08 14:34:01 +02:00
parent bed992d55f
commit b0db646029
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
3 changed files with 26 additions and 24 deletions

View File

@ -19,6 +19,7 @@
#ifndef _ardour_monitor_port_h_
#define _ardour_monitor_port_h_
#include <boost/shared_ptr.hpp>
#include <set>
#include "zita-resampler/vmresampler.h"
@ -26,6 +27,7 @@
#include "pbd/rcu.h"
#include "ardour/audio_buffer.h"
#include "ardour/port_engine.h"
namespace ARDOUR {
@ -50,10 +52,7 @@ public:
protected:
friend class PortManager;
MonitorPort ();
void prepare (std::set<std::string>&);
void monitor (Sample*, pframes_t, std::string const&);
void finalize (pframes_t);
void monitor (PortEngine&, pframes_t);
private:
struct MonitorInfo {
@ -67,10 +66,11 @@ private:
bool remove;
};
typedef std::map<std::string, boost::shared_ptr<MonitorInfo> > MonitorPorts;
void collect (boost::shared_ptr<MonitorInfo>, Sample*, pframes_t, std::string const&);
void finalize (pframes_t);
typedef std::map<std::string, boost::shared_ptr<MonitorInfo> > MonitorPorts;
SerializedRCUManager<MonitorPorts> _monitor_ports;
boost::shared_ptr<MonitorPorts> _cycle_ports;
AudioBuffer* _buffer;
ArdourZita::VMResampler _src;

View File

@ -78,28 +78,37 @@ MonitorPort::silent () const
}
void
MonitorPort::prepare (std::set<std::string>& portset)
MonitorPort::monitor (PortEngine& e, pframes_t n_samples)
{
if (!_silent) {
memset (_input, 0, sizeof (Sample) * _insize);
_silent = true;
}
boost::shared_ptr<MonitorPorts> cycle_ports = _monitor_ports.reader ();
_cycle_ports = _monitor_ports.reader ();
for (MonitorPorts::iterator i = _cycle_ports->begin (); i != _cycle_ports->end(); ++i) {
for (MonitorPorts::iterator i = cycle_ports->begin (); i != cycle_ports->end(); ++i) {
if (i->second->remove && i->second->gain == 0) {
continue;
}
portset.insert (i->first);
PortEngine::PortHandle ph = e.get_port_by_name (i->first);
if (!ph) {
continue;
}
Sample* buf = (Sample*) e.get_buffer (ph, n_samples);
if (!buf) {
continue;
}
collect (i->second, buf, n_samples, i->first);
}
finalize (n_samples);
}
void
MonitorPort::monitor (Sample* buf, pframes_t n_samples, std::string const& pn)
MonitorPort::collect (boost::shared_ptr<MonitorInfo> mi, Sample* buf, pframes_t n_samples, std::string const& pn)
{
MonitorPorts::iterator i = _cycle_ports->find (pn);
gain_t target_gain = i->second->remove ? 0.0 : 1.0;
gain_t current_gain = i->second->gain;
gain_t target_gain = mi->remove ? 0.0 : 1.0;
gain_t current_gain = mi->gain;
if (target_gain == current_gain && target_gain == 0) {
return;
@ -129,7 +138,7 @@ MonitorPort::monitor (Sample* buf, pframes_t n_samples, std::string const& pn)
offset += n_proc;
}
if (fabsf (current_gain - target_gain) < GAIN_COEFF_DELTA) {
i->second->gain = target_gain;
mi->gain = target_gain;
#if 1 // not strictly needed
if (target_gain == 0) {
/* remove port from list, uses RCUWriter */
@ -137,7 +146,7 @@ MonitorPort::monitor (Sample* buf, pframes_t n_samples, std::string const& pn)
}
#endif
} else {
i->second->gain = current_gain;
mi->gain = current_gain;
}
}
_silent = false;
@ -158,7 +167,6 @@ MonitorPort::finalize (pframes_t n_samples)
++_src.out_data;
--_src.out_count;
}
_cycle_ports.reset ();
}
ARDOUR::AudioBuffer&

View File

@ -1765,8 +1765,7 @@ PortManager::run_input_meters (pframes_t n_samples, samplecnt_t rate)
const float falloff = falloff_cache.calc (n_samples, rate);
std::set<std::string> monitor_portset;
_monitor_port.prepare (monitor_portset);
_monitor_port.monitor (port_engine (), n_samples);
/* calculate peak of all physical inputs (readable ports) */
std::vector<std::string> port_names;
@ -1799,9 +1798,6 @@ PortManager::run_input_meters (pframes_t n_samples, samplecnt_t rate)
continue;
}
if (monitor_portset.find (*p) != monitor_portset.end ()) {
_monitor_port.monitor (buf, n_samples, *p);
}
ai->second.scope->write (buf, n_samples);
@ -1818,8 +1814,6 @@ PortManager::run_input_meters (pframes_t n_samples, samplecnt_t rate)
ai->second.meter->peak = std::max (ai->second.meter->peak, level);
}
_monitor_port.finalize (n_samples);
/* MIDI */
port_names.clear ();
get_physical_inputs (DataType::MIDI, port_names);