From f07ea817511902d6ef52d3aa07dc3539fcc4d11c Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Mon, 7 Mar 2011 22:13:53 +0000 Subject: 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 --- libs/ardour/amp.cc | 2 +- libs/ardour/ardour/route.h | 1 + libs/ardour/ardour/track.h | 2 ++ libs/ardour/audio_port.cc | 5 ++++- libs/ardour/route.cc | 42 +++++++++++++++++++++++++++++++++--------- libs/ardour/track.cc | 20 ++++++++++++++++++++ 6 files changed, 61 insertions(+), 11 deletions(-) (limited to 'libs') diff --git a/libs/ardour/amp.cc b/libs/ardour/amp.cc index 5f305182f8..40a1de2047 100644 --- a/libs/ardour/amp.cc +++ b/libs/ardour/amp.cc @@ -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); } diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index 31b62d5e92..3b45020727 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -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); diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h index 74dd95ef13..8faff74bc3 100644 --- a/libs/ardour/ardour/track.h +++ b/libs/ardour/ardour/track.h @@ -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 _rec_enable_control; diff --git a/libs/ardour/audio_port.cc b/libs/ardour/audio_port.cc index f8a1018e29..9deda7a861 100644 --- a/libs/ardour/audio_port.cc +++ b/libs/ardour/audio_port.cc @@ -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()); } } diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 994844a17f..be5ba4f80e 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -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 (*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 pi; + + if ((pi = boost::dynamic_pointer_cast(*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 pi; + + if ((pi = boost::dynamic_pointer_cast(*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 (); } diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc index 5767c45e6e..44f84ca3dc 100644 --- a/libs/ardour/track.cc +++ b/libs/ardour/track.cc @@ -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); + } +} -- cgit v1.2.3