manage Route::_have_internal_generator more accurately and never flush processors if there is on; correctly manage declicking so that only *TRACKS* without internal generators will declick at transport state transitions (fixes horrible click at transport stop in some configurations

git-svn-id: svn://localhost/ardour2/branches/3.0@9100 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis
2011-03-07 22:13:53 +00:00
parent 5a0a06f94f
commit f07ea81751
6 changed files with 61 additions and 11 deletions

View File

@@ -243,7 +243,7 @@ Amp::declick (BufferSet& bufs, framecnt_t nframes, int dir)
if (declick != nframes) {
if (target == 0.0) {
memset (&buffer[declick], 0, sizeof (Sample) * (nframes - declick));
memset (&buffer[declick], 0, sizeof (Sample) * (nframes - declick));
} else if (target != 1.0) {
apply_gain_to_buffer (&buffer[declick], nframes - declick, target);
}

View File

@@ -482,6 +482,7 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember,
ChanCount n_process_buffers ();
virtual bool should_monitor () const;
virtual void maybe_declick (BufferSet&, framecnt_t, int);
virtual int _set_state (const XMLNode&, int, bool call_base);

View File

@@ -202,6 +202,8 @@ class Track : public Route, public PublicDiskstream
XMLNode* pending_state;
bool _destructive;
void maybe_declick (BufferSet&, framecnt_t, int);
virtual bool send_silence () const;
boost::shared_ptr<RecEnableControllable> _rec_enable_control;

View File

@@ -54,7 +54,10 @@ void
AudioPort::cycle_end (pframes_t nframes)
{
if (sends_output() && !_buffer->written()) {
_buffer->silence (nframes);
/* we can't use nframes here because the current buffer capacity may
be shorter than the full buffer size if we split the cycle.
*/
_buffer->silence (_buffer->capacity());
}
}

View File

@@ -379,6 +379,14 @@ Route::set_gain (gain_t val, void *src)
_amp->set_gain (val, src);
}
void
Route::maybe_declick (BufferSet&, framecnt_t, int)
{
/* this is the "bus" implementation and they never declick.
*/
return;
}
/** Process this route for one (sub) cycle (process thread)
*
* @param bufs Scratch buffers to use for the signal path
@@ -399,10 +407,6 @@ Route::process_output_buffers (BufferSet& bufs,
bufs.is_silent (false);
if (!declick) {
declick = _pending_declick;
}
/* figure out if we're going to use gain automation */
if (gain_automation_ok) {
_amp->setup_gain_automation (start_frame, end_frame, nframes);
@@ -418,10 +422,7 @@ Route::process_output_buffers (BufferSet& bufs,
GLOBAL DECLICK (for transport changes etc.)
----------------------------------------------------------------------------------------- */
if (declick != 0) {
Amp::declick (bufs, nframes, declick);
}
maybe_declick (bufs, nframes, declick);
_pending_declick = 0;
/* -------------------------------------------------------------------------------------------
@@ -1057,6 +1058,17 @@ Route::add_processors (const ProcessorList& others, boost::shared_ptr<Processor>
(*i)->ActiveChanged.connect_same_thread (*this, boost::bind (&Session::update_latency_compensation, &_session, false, false));
}
for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
boost::shared_ptr<PluginInsert> pi;
if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
if (pi->is_generator()) {
_have_internal_generator = true;
break;
}
}
}
_output->set_user_latency (0);
}
@@ -2401,10 +2413,22 @@ Route::set_processor_state (const XMLNode& node)
{
Glib::RWLock::WriterLock lm (_processor_lock);
_processors = new_order;
if (must_configure) {
Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
configure_processors_unlocked (0);
}
for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
boost::shared_ptr<PluginInsert> pi;
if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
if (pi->is_generator()) {
_have_internal_generator = true;
break;
}
}
}
}
processors_changed (RouteProcessorChange ());
@@ -2690,7 +2714,7 @@ Route::nonrealtime_handle_transport_stopped (bool /*abort_ignored*/, bool did_lo
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
if (Config->get_plugins_stop_with_transport() && can_flush_processors) {
if (!_have_internal_generator && (Config->get_plugins_stop_with_transport() && can_flush_processors)) {
(*i)->flush ();
}

View File

@@ -690,3 +690,23 @@ Track::send_silence () const
return send_silence;
}
void
Track::maybe_declick (BufferSet& bufs, framecnt_t nframes, int declick)
{
/* never declick if there is an internal generator - we just want it to
keep generating sound without interruption.
*/
if (_have_internal_generator) {
return;
}
if (!declick) {
declick = _pending_declick;
}
if (declick != 0) {
Amp::declick (bufs, nframes, declick);
}
}