Remove global declick API

De-click will be per disk-reader, latency compensated and buffer-size
independent. Cue-monitoring should not be affected by de-click.
This commit is contained in:
Robin Gareus 2018-05-22 18:09:26 +02:00
parent 8664768efa
commit 249640267c
15 changed files with 35 additions and 329 deletions

View File

@ -237,48 +237,6 @@ Amp::apply_gain (BufferSet& bufs, samplecnt_t sample_rate, samplecnt_t nframes,
return rv;
}
void
Amp::declick (BufferSet& bufs, samplecnt_t nframes, int dir)
{
if (nframes == 0 || bufs.count().n_total() == 0) {
return;
}
const samplecnt_t declick = std::min ((samplecnt_t) 512, nframes);
const double fractional_shift = 1.0 / declick ;
gain_t delta, initial;
if (dir < 0) {
/* fade out: remove more and more of delta from initial */
delta = -1.0;
initial = GAIN_COEFF_UNITY;
} else {
/* fade in: add more and more of delta from initial */
delta = 1.0;
initial = GAIN_COEFF_ZERO;
}
/* Audio Gain */
for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
Sample* const buffer = i->data();
double fractional_pos = 0.0;
for (pframes_t nx = 0; nx < declick; ++nx) {
buffer[nx] *= initial + (delta * fractional_pos);
fractional_pos += fractional_shift;
}
/* now ensure the rest of the buffer has the target value applied, if necessary. */
if (declick != nframes) {
if (dir < 0) {
memset (&buffer[declick], 0, sizeof (Sample) * (nframes - declick));
}
}
}
}
gain_t
Amp::apply_gain (AudioBuffer& buf, samplecnt_t sample_rate, samplecnt_t nframes, gain_t initial, gain_t target, sampleoffset_t offset)
{

View File

@ -32,9 +32,7 @@ class BufferSet;
class GainControl;
class IO;
/** Applies a declick operation to all audio inputs, passing the same number of
* audio outputs, and passing through any other types unchanged.
*/
/** Gain Stage (Fader, Trim). */
class LIBARDOUR_API Amp : public Processor {
public:
Amp(Session& s, const std::string& display_name, boost::shared_ptr<GainControl> control, bool control_midi_also);
@ -62,9 +60,6 @@ public:
static gain_t apply_gain (AudioBuffer& buf, samplecnt_t sample_rate, samplecnt_t nframes, gain_t initial, gain_t target, sampleoffset_t offset = 0);
static void apply_simple_gain (AudioBuffer& buf, samplecnt_t nframes, gain_t target, sampleoffset_t offset = 0);
static void declick (BufferSet& bufs, samplecnt_t nframes, int dir);
static void update_meters();
boost::shared_ptr<GainControl> gain_control() {
return _gain_control;
}

View File

@ -70,11 +70,11 @@ class LIBARDOUR_API Auditioner : public Track
PBD::Signal2<void, ARDOUR::samplecnt_t, ARDOUR::samplecnt_t> AuditionProgress;
/* Track */
int roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, int declick, bool& need_butler);
int roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, bool& need_butler);
DataType data_type () const;
int roll_audio (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, int declick, bool& need_butler);
int roll_midi (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, int declick, bool& need_butler);
int roll_audio (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, bool& need_butler);
int roll_midi (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, bool& need_butler);
/* fake track */
void set_state_part_two () {}

View File

@ -65,11 +65,9 @@ public:
void helper_thread();
int process_routes (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, int declick,
bool& need_butler);
int process_routes (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, bool& need_butler);
int routes_no_roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample,
bool non_rt_pending, int declick);
int routes_no_roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, bool non_rt_pending );
void process_one_route (Route * route);
@ -125,7 +123,6 @@ private:
samplepos_t _process_end_sample;
bool _process_can_record;
bool _process_non_rt_pending;
int _process_declick;
bool _process_noroll;
int _process_retval;

View File

@ -142,7 +142,7 @@ public:
virtual void filter_input (BufferSet &) {}
int roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, int declick, bool& need_butler);
int roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, bool& need_butler);
int no_roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, bool state_changing);
@ -154,7 +154,6 @@ public:
virtual void realtime_handle_transport_stopped () {}
virtual void realtime_locate () {}
virtual void non_realtime_locate (samplepos_t);
virtual void set_pending_declick (int);
void set_loop (ARDOUR::Location *);
/* end of vfunc-based API */
@ -586,8 +585,7 @@ public:
/* can only be executed by a route for which is_monitor() is true
* (i.e. the monitor out)
*/
void monitor_run (samplepos_t start_sample, samplepos_t end_sample,
pframes_t nframes, int declick);
void monitor_run (samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes);
bool slaved_to (boost::shared_ptr<VCA>) const;
bool slaved () const;
@ -611,7 +609,7 @@ protected:
void process_output_buffers (BufferSet& bufs,
samplepos_t start_sample, samplepos_t end_sample,
pframes_t nframes, int declick,
pframes_t nframes,
bool gain_automation_ok,
bool run_disk_processors);
@ -657,7 +655,6 @@ protected:
gint _pending_process_reorder; // atomic
gint _pending_signals; // atomic
int _pending_declick;
MeterPoint _meter_point;
MeterPoint _pending_meter_point;
MeterType _meter_type;
@ -665,7 +662,6 @@ protected:
bool _denormal_protection;
bool _recordable : 1;
bool _declickable : 1;
boost::shared_ptr<SoloControl> _solo_control;
boost::shared_ptr<MuteControl> _mute_control;
@ -695,8 +691,6 @@ protected:
uint32_t pans_required() const;
ChanCount n_process_buffers ();
virtual void maybe_declick (BufferSet&, samplecnt_t, int);
boost::shared_ptr<GainControl> _gain_control;
boost::shared_ptr<GainControl> _trim_control;
boost::shared_ptr<PhaseControl> _phase_control;
@ -752,7 +746,7 @@ private:
pframes_t latency_preroll (pframes_t nframes, samplepos_t& start_sample, samplepos_t& end_sample);
void run_route (samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes, int declick, bool gain_automation_ok, bool run_disk_reader);
void run_route (samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes, bool gain_automation_ok, bool run_disk_reader);
void fill_buffers_with_input (BufferSet& bufs, boost::shared_ptr<IO> io, pframes_t nframes);
void reset_instrument_info ();

View File

@ -175,12 +175,8 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
{
private:
enum SubState {
PendingDeclickIn = 0x1, ///< pending de-click fade-in for start
PendingDeclickOut = 0x2, ///< pending de-click fade-out for stop
StopPendingCapture = 0x4,
PendingLoopDeclickIn = 0x8, ///< pending de-click fade-in at the start of a loop
PendingLoopDeclickOut = 0x10, ///< pending de-click fade-out at the end of a loop
PendingLocate = 0x20,
};
public:
@ -440,7 +436,6 @@ public:
bool global_locate_pending() const { return _global_locate_pending; }
bool locate_pending() const { return static_cast<bool>(post_transport_work()&PostTransportLocate); }
bool declick_out_pending() const { return static_cast<bool>(transport_sub_state&(PendingDeclickOut)); }
bool transport_locked () const;
int wipe ();
@ -1376,31 +1371,9 @@ private:
-1 if there is a pending declick fade-out,
0 if there is no pending declick.
*/
int get_transport_declick_required () {
if (transport_sub_state & PendingDeclickIn) {
transport_sub_state &= ~PendingDeclickIn;
return 1;
} else if (transport_sub_state & PendingDeclickOut) {
/* XXX: not entirely sure why we don't clear this */
return -1;
} else if (transport_sub_state & PendingLoopDeclickOut) {
/* Return the declick out first ... */
transport_sub_state &= ~PendingLoopDeclickOut;
return -1;
} else if (transport_sub_state & PendingLoopDeclickIn) {
/* ... then the declick in on the next call */
transport_sub_state &= ~PendingLoopDeclickIn;
return 1;
} else {
return 0;
}
}
bool maybe_stop (samplepos_t limit);
bool maybe_sync_start (pframes_t &);
void check_declick_out ();
std::string _path;
std::string _name;
bool _is_new;
@ -1443,9 +1416,6 @@ private:
samplepos_t _last_roll_or_reversal_location;
samplepos_t _last_record_location;
bool pending_locate_roll;
samplepos_t pending_locate_sample;
bool pending_locate_flush;
bool pending_abort;
bool pending_auto_loop;

View File

@ -209,8 +209,6 @@ protected:
XMLNode* pending_state;
bool _destructive;
void maybe_declick (BufferSet&, samplecnt_t, int);
boost::shared_ptr<AutomationControl> _record_enable_control;
boost::shared_ptr<AutomationControl> _record_safe_control;

View File

@ -220,7 +220,7 @@ Auditioner::data_type () const {
}
int
Auditioner::roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, int declick, bool& need_butler)
Auditioner::roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, bool& need_butler)
{
Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
if (!lm.locked()) {
@ -244,7 +244,7 @@ Auditioner::roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_s
}
}
process_output_buffers (bufs, start_sample, end_sample, nframes, declick, !_session.transport_stopped(), true);
process_output_buffers (bufs, start_sample, end_sample, nframes, !_session.transport_stopped(), true);
/* note: auditioner never writes to disk, so we don't care about the
* disk writer status (it's buffers will always have no data in them).
@ -425,7 +425,7 @@ Auditioner::play_audition (samplecnt_t nframes)
/* process audio */
this_nframes = min (nframes, length - current_sample + _import_position);
if (this_nframes > 0 && 0 != (ret = roll (this_nframes, current_sample, current_sample + this_nframes, false, need_butler))) {
if (this_nframes > 0 && 0 != (ret = roll (this_nframes, current_sample, current_sample + this_nframes, need_butler))) {
silence (nframes);
return ret;
}

View File

@ -412,7 +412,7 @@ DiskReader::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
/* MIDI data handling */
midi:
if (!_session.declick_out_pending() && bufs.count().n_midi()) {
if (/*!_session.declick_out_pending() && */ bufs.count().n_midi()) {
MidiBuffer* dst;
if (_no_disk_output) {

View File

@ -513,7 +513,7 @@ Graph::dump (int chain)
}
int
Graph::process_routes (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, int declick, bool& need_butler)
Graph::process_routes (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, bool& need_butler)
{
DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("graph execution from %1 to %2 = %3\n", start_sample, end_sample, nframes));
@ -522,7 +522,6 @@ Graph::process_routes (pframes_t nframes, samplepos_t start_sample, samplepos_t
_process_nframes = nframes;
_process_start_sample = start_sample;
_process_end_sample = end_sample;
_process_declick = declick;
_process_noroll = false;
_process_retval = 0;
@ -539,8 +538,7 @@ Graph::process_routes (pframes_t nframes, samplepos_t start_sample, samplepos_t
}
int
Graph::routes_no_roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample,
bool non_rt_pending, int declick)
Graph::routes_no_roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, bool non_rt_pending)
{
DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("no-roll graph execution from %1 to %2 = %3\n", start_sample, end_sample, nframes));
@ -549,7 +547,6 @@ Graph::routes_no_roll (pframes_t nframes, samplepos_t start_sample, samplepos_t
_process_nframes = nframes;
_process_start_sample = start_sample;
_process_end_sample = end_sample;
_process_declick = declick;
_process_non_rt_pending = non_rt_pending;
_process_noroll = true;
@ -574,11 +571,9 @@ Graph::process_one_route (Route* route)
DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("%1 runs route %2\n", pthread_name(), route->name()));
if (_process_noroll) {
route->set_pending_declick (_process_declick);
retval = route->no_roll (_process_nframes, _process_start_sample, _process_end_sample, _process_non_rt_pending);
} else {
route->set_pending_declick (_process_declick);
retval = route->roll (_process_nframes, _process_start_sample, _process_end_sample, _process_declick, need_butler);
retval = route->roll (_process_nframes, _process_start_sample, _process_end_sample, need_butler);
}
if (retval) {

View File

@ -100,13 +100,11 @@ Route::Route (Session& sess, string name, PresentationInfo::Flag flag, DataType
, _disk_io_point (DiskIOPreFader)
, _pending_process_reorder (0)
, _pending_signals (0)
, _pending_declick (true)
, _meter_point (MeterPostFader)
, _pending_meter_point (MeterPostFader)
, _meter_type (MeterPeak)
, _denormal_protection (false)
, _recordable (true)
, _declickable (false)
, _have_internal_generator (false)
, _default_type (default_type)
, _loop_location (NULL)
@ -292,14 +290,6 @@ Route::set_trim (gain_t val, Controllable::GroupControlDisposition /* group over
// _trim_control->route_set_value (val);
}
void
Route::maybe_declick (BufferSet&, samplecnt_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
@ -313,7 +303,7 @@ Route::maybe_declick (BufferSet&, samplecnt_t, int)
void
Route::process_output_buffers (BufferSet& bufs,
samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes,
int declick, bool gain_automation_ok, bool run_disk_reader)
bool gain_automation_ok, bool run_disk_reader)
{
/* Caller must hold process lock */
assert (!AudioEngine::instance()->process_lock().trylock());
@ -422,15 +412,6 @@ Route::process_output_buffers (BufferSet& bufs,
_main_outs->no_outs_cuz_we_no_monitor (silence);
/* -------------------------------------------------------------------------------------------
GLOBAL DECLICK (for transport changes etc.)
----------------------------------------------------------------------------------------- */
// XXX not latency compensated. calls Amp::declick, but there may be
// plugins between disk and Fader.
maybe_declick (bufs, nframes, declick);
_pending_declick = 0;
/* -------------------------------------------------------------------------------------------
DENORMAL CONTROL
----------------------------------------------------------------------------------------- */
@ -658,15 +639,15 @@ Route::n_process_buffers ()
}
void
Route::monitor_run (samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes, int declick)
Route::monitor_run (samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes)
{
assert (is_monitor());
Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
run_route (start_sample, end_sample, nframes, declick, true, false);
run_route (start_sample, end_sample, nframes, true, false);
}
void
Route::run_route (samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes, int declick, bool gain_automation_ok, bool run_disk_reader)
Route::run_route (samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes, bool gain_automation_ok, bool run_disk_reader)
{
BufferSet& bufs (_session.get_route_buffers (n_process_buffers()));
@ -692,7 +673,7 @@ Route::run_route (samplepos_t start_sample, samplepos_t end_sample, pframes_t nf
/* run processor chain */
process_output_buffers (bufs, start_sample, end_sample, nframes, declick, gain_automation_ok, run_disk_reader);
process_output_buffers (bufs, start_sample, end_sample, nframes, gain_automation_ok, run_disk_reader);
/* map events (e.g. MIDI-CC) back to control-parameters */
update_controls (bufs);
@ -3670,7 +3651,7 @@ Route::latency_preroll (pframes_t nframes, samplepos_t& start_sample, samplepos_
}
int
Route::roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, int declick, bool& need_butler)
Route::roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, bool& need_butler)
{
Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
@ -3688,7 +3669,7 @@ Route::roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample
return 0;
}
run_route (start_sample, end_sample, nframes, declick, (!_disk_writer || !_disk_writer->record_enabled()) && _session.transport_rolling(), true);
run_route (start_sample, end_sample, nframes, (!_disk_writer || !_disk_writer->record_enabled()) && _session.transport_rolling(), true);
if ((_disk_reader && _disk_reader->need_butler()) || (_disk_writer && _disk_writer->need_butler())) {
need_butler = true;
@ -3735,7 +3716,7 @@ Route::no_roll_unlocked (pframes_t nframes, samplepos_t start_sample, samplepos_
*/
}
run_route (start_sample, end_sample, nframes, 0, false, false);
run_route (start_sample, end_sample, nframes, false, false);
return 0;
}
@ -4099,22 +4080,6 @@ Route::protect_automation ()
(*i)->protect_automation();
}
/** @param declick 1 to set a pending declick fade-in,
* -1 to set a pending declick fade-out
*/
void
Route::set_pending_declick (int declick)
{
if (_declickable) {
/* this call is not allowed to turn off a pending declick */
if (declick) {
_pending_declick = declick;
}
} else {
_pending_declick = 0;
}
}
/** Shift automation forwards from a particular place, thereby inserting time.
* Adds undo commands for any shifts that are performed.
*

View File

@ -243,10 +243,6 @@ Session::Session (AudioEngine &eng,
, _last_roll_location (0)
, _last_roll_or_reversal_location (0)
, _last_record_location (0)
, pending_locate_roll (false)
, pending_locate_sample (0)
, pending_locate_flush (false)
, pending_abort (false)
, pending_auto_loop (false)
, _mempool ("Session", 3145728)
, lua (lua_newstate (&PBD::ReallocPool::lalloc, &_mempool))

View File

@ -136,7 +136,6 @@ Session::no_roll (pframes_t nframes)
samplepos_t end_sample = _transport_sample + nframes; // FIXME: varispeed + no_roll ??
int ret = 0;
int declick = (config.get_use_transport_fades() ? get_transport_declick_required() : false);
boost::shared_ptr<RouteList> r = routes.reader ();
if (_click_io) {
@ -152,7 +151,7 @@ Session::no_roll (pframes_t nframes)
if (_process_graph) {
DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/no-roll\n");
_process_graph->routes_no_roll( nframes, _transport_sample, end_sample, non_realtime_work_pending(), declick);
_process_graph->routes_no_roll( nframes, _transport_sample, end_sample, non_realtime_work_pending());
} else {
PT_TIMING_CHECK (10);
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
@ -161,8 +160,6 @@ Session::no_roll (pframes_t nframes)
continue;
}
(*i)->set_pending_declick (declick);
if ((*i)->no_roll (nframes, _transport_sample, end_sample, non_realtime_work_pending())) {
error << string_compose(_("Session: error in no roll for %1"), (*i)->name()) << endmsg;
ret = -1;
@ -182,7 +179,6 @@ Session::no_roll (pframes_t nframes)
int
Session::process_routes (pframes_t nframes, bool& need_butler)
{
int declick = (config.get_use_transport_fades() ? get_transport_declick_required() : false);
boost::shared_ptr<RouteList> r = routes.reader ();
const samplepos_t start_sample = _transport_sample;
@ -197,7 +193,7 @@ Session::process_routes (pframes_t nframes, bool& need_butler)
if (_process_graph) {
DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/process-routes\n");
if (_process_graph->process_routes (nframes, start_sample, end_sample, declick, need_butler) < 0) {
if (_process_graph->process_routes (nframes, start_sample, end_sample, need_butler) < 0) {
stop_transport ();
return -1;
}
@ -211,11 +207,9 @@ Session::process_routes (pframes_t nframes, bool& need_butler)
continue;
}
(*i)->set_pending_declick (declick);
bool b = false;
if ((ret = (*i)->roll (nframes, start_sample, end_sample, declick, b)) < 0) {
if ((ret = (*i)->roll (nframes, start_sample, end_sample, b)) < 0) {
stop_transport ();
return -1;
}
@ -369,8 +363,6 @@ Session::process_with_events (pframes_t nframes)
set_next_event ();
}
check_declick_out ();
if (nframes == 0) {
return;
} else {
@ -514,7 +506,6 @@ Session::process_with_events (pframes_t nframes)
}
maybe_stop (stop_limit);
check_declick_out ();
}
if (nframes > 0) {
@ -920,7 +911,6 @@ Session::process_without_events (pframes_t nframes)
}
maybe_stop (stop_limit);
check_declick_out ();
if (session_needs_butler) {
DEBUG_TRACE (DEBUG::Butler, "p-without-events: session needs butler, call it\n");
@ -953,7 +943,7 @@ Session::process_audition (pframes_t nframes)
/* if using a monitor section, run it because otherwise we don't hear anything */
if (_monitor_out && auditioner->needs_monitor()) {
_monitor_out->monitor_run (_transport_sample, _transport_sample + nframes, nframes, false);
_monitor_out->monitor_run (_transport_sample, _transport_sample + nframes, nframes);
}
/* handle pending events */

View File

@ -808,12 +808,6 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
boost::shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
if (!(*i)->is_auditioner()) {
(*i)->set_pending_declick (0);
}
}
if (did_record) {
commit_reversible_command ();
/* increase take name */
@ -827,11 +821,11 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
PostTransportWork ptw = post_transport_work ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
(*i)->non_realtime_transport_stop (_transport_sample, !(ptw & PostTransportLocate) || pending_locate_flush);
(*i)->non_realtime_transport_stop (_transport_sample, !(ptw & PostTransportLocate));
}
VCAList v = _vca_manager->vcas ();
for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
(*i)->non_realtime_transport_stop (_transport_sample, !(ptw & PostTransportLocate) || pending_locate_flush);
(*i)->non_realtime_transport_stop (_transport_sample, !(ptw & PostTransportLocate));
}
update_latency_compensation ();
@ -844,10 +838,6 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
(_requested_return_sample >= 0) ||
synced_to_engine()) {
if (pending_locate_flush) {
flush_all_inserts ();
}
// rg: what is the logic behind this case?
// _requested_return_sample should be ignored when synced_to_engine/slaved.
// currently worked around in MTC_Slave by forcing _requested_return_sample to -1
@ -988,44 +978,9 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
/* and start it up again if relevant */
if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
if ((ptw & PostTransportLocate) && !config.get_external_sync()) {
request_transport_speed (1.0);
}
/* Even if we didn't do a pending locate roll this time, we don't want it hanging
around for next time.
*/
pending_locate_roll = false;
}
void
Session::check_declick_out ()
{
bool locate_required = transport_sub_state & PendingLocate;
/* this is called after a process() iteration. if PendingDeclickOut was set,
it means that we were waiting to declick the output (which has just been
done) before maybe doing something else. this is where we do that "something else".
note: called from the audio thread.
*/
if (transport_sub_state & PendingDeclickOut) {
if (locate_required) {
start_locate (pending_locate_sample, pending_locate_roll, pending_locate_flush);
transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
} else {
if (!(transport_sub_state & StopPendingCapture)) {
stop_transport (pending_abort);
transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
}
}
} else if (transport_sub_state & PendingLoopDeclickOut) {
/* Nothing else to do here; we've declicked, and the loop event will be along shortly */
transport_sub_state &= ~PendingLoopDeclickOut;
}
}
void
@ -1259,22 +1214,6 @@ Session::locate (samplepos_t target_sample, bool with_roll, bool with_flush, boo
return;
}
if (_transport_speed && !(for_loop_enabled && Config->get_seamless_loop())) {
/* Schedule a declick. We'll be called again when its done.
We only do it this way for ordinary locates, not those
due to **seamless** loops.
*/
if (!(transport_sub_state & PendingDeclickOut)) {
transport_sub_state |= (PendingDeclickOut|PendingLocate);
pending_locate_sample = target_sample;
pending_locate_roll = with_roll;
pending_locate_flush = with_flush;
cerr << "Declick scheduled ... back soon\n";
return;
}
}
cerr << "... now doing the actual locate\n";
// Update Timecode time
@ -1622,74 +1561,10 @@ Session::stop_transport (bool abort, bool clear_state)
return;
}
DEBUG_TRACE (DEBUG::Transport, string_compose ("stop_transport, declick required? %1\n", get_transport_declick_required()));
DEBUG_TRACE (DEBUG::Transport, "time to actually stop\n");
if (!get_transport_declick_required()) {
/* stop has not yet been scheduled */
boost::shared_ptr<RouteList> rl = routes.reader();
samplepos_t stop_target = audible_sample();
SubState new_bits;
if (actively_recording() && /* we are recording */
worst_input_latency() > current_block_size) { /* input latency exceeds block size, so simple 1 cycle delay before stop is not enough */
/* we need to capture the audio that is still somewhere in the pipeline between
wherever it was generated and the process callback. This means that even though
the user (or something else) has asked us to stop, we have to roll
past this point and then reset the playhead/transport location to
the position at which the stop was requested.
we still need playback to "stop" now, however, which is why we schedule
a declick below.
*/
DEBUG_TRACE (DEBUG::Transport, string_compose ("stop transport requested @ %1, scheduled for + %2 = %3, abort = %4\n",
_transport_sample, _worst_input_latency,
_transport_sample + _worst_input_latency,
abort));
SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
_transport_sample + _worst_input_latency,
0, 0, abort);
merge_event (ev);
/* request a declick at the start of the next process cycle() so that playback ceases.
It will remain silent until we actually stop (at the StopOnce event somewhere in
the future). The extra flag (StopPendingCapture) is set to ensure that check_declick_out()
does not stop the transport too early.
*/
new_bits = SubState (PendingDeclickOut|StopPendingCapture);
} else {
/* Not recording, schedule a declick in the next process() cycle and then stop at its end */
new_bits = PendingDeclickOut;
DEBUG_TRACE (DEBUG::Transport, string_compose ("stop scheduled for next process cycle @ %1\n", _transport_sample));
}
/* we'll be called again after the declick */
transport_sub_state = SubState (transport_sub_state|new_bits);
pending_abort = abort;
return;
} else {
DEBUG_TRACE (DEBUG::Transport, "time to actually stop\n");
/* declick was scheduled, but we've been called again, which means it is really time to stop
XXX: we should probably split this off into its own method and call it explicitly.
*/
realtime_stop (abort, clear_state);
_butler->schedule_transport_work ();
}
realtime_stop (abort, clear_state);
_butler->schedule_transport_work ();
}
/** Called from the process thread */
@ -1732,8 +1607,6 @@ Session::start_transport ()
break;
}
transport_sub_state |= PendingDeclickIn;
_transport_speed = _default_transport_speed;
_target_transport_speed = _transport_speed;

View File

@ -61,8 +61,6 @@ Track::Track (Session& sess, string name, PresentationInfo::Flag flag, TrackMode
, _alignment_choice (Automatic)
{
_freeze_record.state = NoFreeze;
_declickable = true;
}
Track::~Track ()
@ -801,29 +799,6 @@ Track::adjust_capture_buffering ()
}
}
void
Track::maybe_declick (BufferSet& bufs, samplecnt_t nframes, int declick)
{
/* never declick if there is an internal generator - we just want it to
keep generating sound without interruption.
ditto if we are monitoring inputs.
*/
if (_have_internal_generator || (_monitoring_control->monitoring_choice() == MonitorInput)) {
return;
}
if (!declick) {
declick = _pending_declick;
}
if (declick != 0) {
Amp::declick (bufs, nframes, declick);
}
}
void
Track::monitoring_changed (bool, Controllable::GroupControlDisposition)
{