summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2017-09-18 21:27:55 -0400
committerPaul Davis <paul@linuxaudiosystems.com>2017-09-18 21:28:02 -0400
commit40aebce6996abeccf46729ca069355f3bb34e5af (patch)
treee9cc8c66a3afe6979c0ae7493fca58fadbdedbec
parent10b76ae631d971611bcb389d18995942300d0404 (diff)
consolidate roll methods into Route::roll()
We want Track to shrink, and logic consolidation is always good. Route already knew about disk_reader and disk_writer, now it knows about _monitoring_control too
-rw-r--r--libs/ardour/ardour/audio_track.h3
-rw-r--r--libs/ardour/ardour/midi_track.h4
-rw-r--r--libs/ardour/ardour/route.h15
-rw-r--r--libs/ardour/ardour/track.h8
-rw-r--r--libs/ardour/audio_track.cc46
-rw-r--r--libs/ardour/midi_track.cc61
-rw-r--r--libs/ardour/route.cc203
-rw-r--r--libs/ardour/track.cc148
8 files changed, 195 insertions, 293 deletions
diff --git a/libs/ardour/ardour/audio_track.h b/libs/ardour/ardour/audio_track.h
index e93ebd7f02..945dc52b31 100644
--- a/libs/ardour/ardour/audio_track.h
+++ b/libs/ardour/ardour/audio_track.h
@@ -37,9 +37,6 @@ class LIBARDOUR_API AudioTrack : public Track
AudioTrack (Session&, std::string name, TrackMode m = Normal);
~AudioTrack ();
- int roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample,
- int declick, bool& need_butler);
-
void freeze_me (InterThreadInfo&);
void unfreeze ();
diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h
index 54a04d8ed3..023c18926b 100644
--- a/libs/ardour/ardour/midi_track.h
+++ b/libs/ardour/ardour/midi_track.h
@@ -42,8 +42,6 @@ public:
int init ();
- int roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, int declick, bool& need_butler);
-
void realtime_locate ();
void non_realtime_locate (samplepos_t);
@@ -120,6 +118,8 @@ public:
MidiChannelFilter& playback_filter() { return _playback_filter; }
MidiChannelFilter& capture_filter() { return _capture_filter; }
+ virtual void filter_input (BufferSet& bufs);
+
boost::shared_ptr<MidiPlaylist> midi_playlist ();
PBD::Signal1<void, boost::weak_ptr<MidiSource> > DataRecorded;
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index 1ecf36d445..0e1d0b65e1 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -77,6 +77,7 @@ class PluginInsert;
class RouteGroup;
class Send;
class InternalReturn;
+class MonitorControl;
class MonitorProcessor;
class Pannable;
class CapturingProcessor;
@@ -128,11 +129,15 @@ public:
bool set_name (const std::string& str);
static void set_name_in_state (XMLNode &, const std::string &, bool rename_playlist = true);
+ boost::shared_ptr<MonitorControl> monitoring_control() const { return _monitoring_control; }
+
MonitorState monitoring_state () const;
virtual MeterState metering_state () const;
/* these are the core of the API of a Route. see the protected sections as well */
+ virtual void filter_input (BufferSet &) {}
+
virtual int roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample,
int declick, bool& need_butler);
@@ -474,13 +479,6 @@ public:
return _solo_safe_control;
}
- boost::shared_ptr<MonitorControl> monitoring_control() const {
- /* tracks override this to provide actual monitoring control;
- busses have no possible choices except input monitoring.
- */
- return boost::shared_ptr<MonitorControl> ();
- }
-
/* Route doesn't own these items, but sub-objects that it does own have them
and to make UI code a bit simpler, we provide direct access to them
here.
@@ -603,7 +601,7 @@ public:
void fill_buffers_with_input (BufferSet& bufs, boost::shared_ptr<IO> io, pframes_t nframes);
- void passthru (BufferSet&, samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes, int declick);
+ void passthru (BufferSet&, samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes, int declick, bool gain_automation_ok);
virtual void write_out_of_band_data (BufferSet& /* bufs */, samplepos_t /* start_sample */, samplepos_t /* end_sample */,
samplecnt_t /* nframes */) {}
@@ -640,6 +638,7 @@ public:
boost::shared_ptr<Pannable> _pannable;
boost::shared_ptr<DiskReader> _disk_reader;
boost::shared_ptr<DiskWriter> _disk_writer;
+ boost::shared_ptr<MonitorControl> _monitoring_control;
DiskIOPoint _disk_io_point;
diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h
index 9d00f812d3..ec81e92939 100644
--- a/libs/ardour/ardour/track.h
+++ b/libs/ardour/ardour/track.h
@@ -38,7 +38,6 @@ class DiskReader;
class DiskWriter;
class IO;
class Location;
-class MonitorControl;
class RecordEnableControl;
class RecordSafeControl;
@@ -62,9 +61,6 @@ class LIBARDOUR_API Track : public Route, public Recordable
TrackMode mode () const { return _mode; }
- boost::shared_ptr<MonitorControl> monitoring_control() const { return _monitoring_control; }
-
- MonitorState monitoring_state () const;
MeterState metering_state () const;
bool set_processor_state (XMLNode const & node, XMLProperty const* prop, ProcessorList& new_order, bool& must_configure);
@@ -72,9 +68,6 @@ class LIBARDOUR_API Track : public Route, public Recordable
virtual int no_roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample,
bool state_changing);
- virtual int roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample,
- int declick, bool& need_butler) = 0;
-
bool needs_butler() const { return _needs_butler; }
bool can_record();
@@ -197,7 +190,6 @@ class LIBARDOUR_API Track : public Route, public Recordable
MeterPoint _saved_meter_point;
TrackMode _mode;
bool _needs_butler;
- boost::shared_ptr<MonitorControl> _monitoring_control;
//private: (FIXME)
struct FreezeRecordProcessorInfo {
diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc
index 403d48f5c0..efce77f6d8 100644
--- a/libs/ardour/audio_track.cc
+++ b/libs/ardour/audio_track.cc
@@ -222,52 +222,6 @@ AudioTrack::set_state_part_two ()
}
}
-/** @param need_butler to be set to true if this track now needs the butler, otherwise it can be left alone
- * or set to false.
- */
-int
-AudioTrack::roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, int declick, bool& need_butler)
-{
- Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
-
- if (!lm.locked()) {
- return 0;
- }
-
- if (n_outputs().n_total() == 0 && _processors.empty()) {
- return 0;
- }
-
- if (!_active) {
- silence (nframes);
- if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _disk_writer->record_enabled())) {
- _meter->reset();
- }
- return 0;
- }
-
- _silent = false;
- _amp->apply_gain_automation(false);
-
- BufferSet& bufs = _session.get_route_buffers (n_process_buffers ());
-
- fill_buffers_with_input (bufs, _input, nframes);
-
- if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _disk_writer->record_enabled())) {
- _meter->run (bufs, start_sample, end_sample, 1.0 /*speed()*/, nframes, true);
- }
-
- process_output_buffers (bufs, start_sample, end_sample, nframes, declick, (!_disk_writer->record_enabled() && _session.transport_rolling()));
-
- if (_disk_reader->need_butler() || _disk_writer->need_butler()) {
- need_butler = true;
- }
-
- flush_processor_buffers_locked (nframes);
-
- return 0;
-}
-
int
AudioTrack::export_stuff (BufferSet& buffers, samplepos_t start, samplecnt_t nframes,
boost::shared_ptr<Processor> endpoint, bool include_endpoint, bool for_export, bool for_freeze)
diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc
index 91916bd914..4832ccce07 100644
--- a/libs/ardour/midi_track.cc
+++ b/libs/ardour/midi_track.cc
@@ -317,61 +317,6 @@ MidiTrack::update_controls(const BufferSet& bufs)
}
}
-/** @param need_butler to be set to true if this track now needs the butler, otherwise it can be left alone
- * or set to false.
- */
-int
-MidiTrack::roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, int declick, bool& need_butler)
-{
- Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
-
- if (!lm.locked()) {
- return 0;
- }
-
- if (n_outputs().n_total() == 0 && _processors.empty()) {
- return 0;
- }
-
- if (!_active) {
- silence (nframes);
- if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _disk_writer->record_enabled())) {
- _meter->reset();
- }
- return 0;
- }
-
- _silent = false;
- _amp->apply_gain_automation (false);
-
- BufferSet& bufs = _session.get_route_buffers (n_process_buffers());
-
- fill_buffers_with_input (bufs, _input, nframes);
-
- /* filter captured data before meter sees it */
- _capture_filter.filter (bufs);
-
- if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _disk_writer->record_enabled())) {
- _meter->run (bufs, start_sample, end_sample, 1.0 /*speed()*/, nframes, true);
- }
-
- /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
-
- write_out_of_band_data (bufs, start_sample, end_sample, nframes);
-
- /* final argument: don't waste time with automation if we're not recording or rolling */
-
- process_output_buffers (bufs, start_sample, end_sample, nframes, declick, (!_disk_writer->record_enabled() && !_session.transport_stopped()));
-
- if (_disk_reader->need_butler() || _disk_writer->need_butler()) {
- need_butler = true;
- }
-
- flush_processor_buffers_locked (nframes);
-
- return 0;
-}
-
int
MidiTrack::no_roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, bool state_changing)
{
@@ -863,3 +808,9 @@ MidiTrack::monitoring_state () const
}
return ms;
}
+
+void
+MidiTrack::filter_input (BufferSet& bufs)
+{
+ _capture_filter.filter (bufs);
+}
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index f0bd724e44..a3ff8c1fa5 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -57,6 +57,7 @@
#include "ardour/delayline.h"
#include "ardour/midi_buffer.h"
#include "ardour/midi_port.h"
+#include "ardour/monitor_control.h"
#include "ardour/monitor_processor.h"
#include "ardour/pannable.h"
#include "ardour/panner.h"
@@ -598,11 +599,11 @@ Route::monitor_run (samplepos_t start_sample, samplepos_t end_sample, pframes_t
assert (is_monitor());
BufferSet& bufs (_session.get_route_buffers (n_process_buffers()));
fill_buffers_with_input (bufs, _input, nframes);
- passthru (bufs, start_sample, end_sample, nframes, declick);
+ passthru (bufs, start_sample, end_sample, nframes, declick, true);
}
void
-Route::passthru (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes, int declick)
+Route::passthru (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, pframes_t nframes, int declick, bool gain_automation_ok)
{
_silent = false;
@@ -616,8 +617,13 @@ Route::passthru (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
bufs.silence (nframes, 0);
}
+ /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
+
write_out_of_band_data (bufs, start_sample, end_sample, nframes);
- process_output_buffers (bufs, start_sample, end_sample, nframes, declick, true);
+
+ /* run processor chain */
+
+ process_output_buffers (bufs, start_sample, end_sample, nframes, declick, gain_automation_ok);
}
void
@@ -3581,7 +3587,7 @@ Route::no_roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sam
_amp->apply_gain_automation (false);
_trim->apply_gain_automation (false);
- passthru (bufs, start_sample, end_sample, nframes, 0);
+ passthru (bufs, start_sample, end_sample, nframes, 0, true);
flush_processor_buffers_locked (nframes);
@@ -3589,35 +3595,42 @@ Route::no_roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sam
}
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, int declick, bool& need_butler)
{
Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
+
if (!lm.locked()) {
return 0;
}
if (!_active) {
silence_unlocked (nframes);
- return 0;
- }
-
- samplepos_t unused = 0;
-
- if ((nframes = check_initial_delay (nframes, unused)) == 0) {
+ if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || (!_disk_writer || _disk_writer->record_enabled()))) {
+ _meter->reset();
+ }
return 0;
}
_silent = false;
+ _amp->apply_gain_automation(false);
- BufferSet& bufs = _session.get_route_buffers (n_process_buffers());
+ BufferSet& bufs = _session.get_route_buffers (n_process_buffers ());
fill_buffers_with_input (bufs, _input, nframes);
- if (_meter_point == MeterInput) {
- _meter->run (bufs, start_sample, end_sample, 1.0, nframes, true);
+ /* filter captured data before meter sees it */
+ filter_input (bufs);
+
+ if (_meter_point == MeterInput &&
+ ((_monitoring_control->monitoring_choice() & MonitorInput) || (_disk_writer && _disk_writer->record_enabled()))) {
+ _meter->run (bufs, start_sample, end_sample, 1.0 /*speed()*/, nframes, true);
}
- passthru (bufs, start_sample, end_sample, nframes, declick);
+ passthru (bufs, start_sample, end_sample, nframes, declick, ((_disk_writer && !_disk_writer->record_enabled()) && _session.transport_rolling()));
+
+ if ((_disk_reader && _disk_reader->need_butler()) || (_disk_writer && _disk_writer->need_butler())) {
+ need_butler = true;
+ }
flush_processor_buffers_locked (nframes);
@@ -4811,15 +4824,6 @@ Route::processor_by_id (PBD::ID id) const
return boost::shared_ptr<Processor> ();
}
-/** @return the monitoring state, or in other words what data we are pushing
- * into the route (data from the inputs, data from disk or silence)
- */
-MonitorState
-Route::monitoring_state () const
-{
- return MonitoringInput;
-}
-
/** @return what we should be metering; either the data coming from the input
* IO or the data that is flowing through the route.
*/
@@ -5670,3 +5674,154 @@ Route::set_disk_io_point (DiskIOPoint diop)
processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
}
+
+#ifdef USE_TRACKS_CODE_FEATURES
+
+/* This is the Tracks version of Track::monitoring_state().
+ *
+ * Ardour developers: try to flag or fix issues if parts of the libardour API
+ * change in ways that invalidate this
+ */
+
+MonitorState
+Route::monitoring_state () const
+{
+ /* Explicit requests */
+
+ if (_monitoring != MonitorInput) {
+ return MonitoringInput;
+ }
+
+ if (_monitoring & MonitorDisk) {
+ return MonitoringDisk;
+ }
+
+ /* This is an implementation of the truth table in doc/monitor_modes.pdf;
+ I don't think it's ever going to be too pretty too look at.
+ */
+
+ // GZ: NOT USED IN TRACKS
+ //bool const auto_input = _session.config.get_auto_input ();
+ //bool const software_monitor = Config->get_monitoring_model() == SoftwareMonitoring;
+ //bool const tape_machine_mode = Config->get_tape_machine_mode ();
+
+ bool const roll = _session.transport_rolling ();
+ bool const track_rec = _diskstream->record_enabled ();
+ bool session_rec = _session.actively_recording ();
+
+ if (track_rec) {
+
+ if (!session_rec && roll) {
+ return MonitoringDisk;
+ } else {
+ return MonitoringInput;
+ }
+
+ } else {
+
+ if (roll) {
+ return MonitoringDisk;
+ }
+ }
+
+ return MonitoringSilence;
+}
+
+#else
+
+/* This is the Ardour/Mixbus version of Track::monitoring_state().
+ *
+ * Tracks developers: do NOT modify this method under any circumstances.
+ */
+
+MonitorState
+Route::monitoring_state () const
+{
+ if (!_disk_reader) {
+ return MonitoringInput;
+ }
+
+ /* Explicit requests */
+ MonitorChoice m (_monitoring_control->monitoring_choice());
+
+ if (m != MonitorAuto) {
+
+ MonitorState ms ((MonitorState) 0);
+
+ if (m & MonitorInput) {
+ ms = MonitoringInput;
+ }
+
+ if (m & MonitorDisk) {
+ ms = MonitorState (ms | MonitoringDisk);
+ }
+
+ return ms;
+ }
+
+ switch (_session.config.get_session_monitoring ()) {
+ case MonitorDisk:
+ return MonitoringDisk;
+ break;
+ case MonitorInput:
+ return MonitoringInput;
+ break;
+ default:
+ break;
+ }
+
+ /* This is an implementation of the truth table in doc/monitor_modes.pdf;
+ I don't think it's ever going to be too pretty too look at.
+ */
+
+ bool const roll = _session.transport_rolling ();
+ bool const track_rec = _disk_writer->record_enabled ();
+ bool const auto_input = _session.config.get_auto_input ();
+ bool const software_monitor = Config->get_monitoring_model() == SoftwareMonitoring;
+ bool const tape_machine_mode = Config->get_tape_machine_mode ();
+ bool session_rec;
+
+ /* I suspect that just use actively_recording() is good enough all the
+ * time, but just to keep the semantics the same as they were before
+ * sept 26th 2012, we differentiate between the cases where punch is
+ * enabled and those where it is not.
+ *
+ * rg: I suspect this is not the case: monitoring may differ
+ */
+
+ if (_session.config.get_punch_in() || _session.config.get_punch_out() || _session.preroll_record_punch_enabled ()) {
+ session_rec = _session.actively_recording ();
+ } else {
+ session_rec = _session.get_record_enabled();
+ }
+
+ if (track_rec) {
+
+ if (!session_rec && roll && auto_input) {
+ return MonitoringDisk;
+ } else {
+ return software_monitor ? MonitoringInput : MonitoringSilence;
+ }
+
+ } else {
+
+ if (tape_machine_mode) {
+
+ return MonitoringDisk;
+
+ } else {
+
+ if (!roll && auto_input) {
+ return software_monitor ? MonitoringInput : MonitoringSilence;
+ } else {
+ return MonitoringDisk;
+ }
+
+ }
+ }
+
+ abort(); /* NOTREACHED */
+ return MonitoringSilence;
+}
+
+#endif
diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc
index d925c2c40d..48235417a5 100644
--- a/libs/ardour/track.cc
+++ b/libs/ardour/track.cc
@@ -548,7 +548,7 @@ Track::no_roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sam
_meter->run (bufs, start_sample, end_sample, _session.transport_speed(), nframes, true);
}
- passthru (bufs, start_sample, end_sample, nframes, false);
+ passthru (bufs, start_sample, end_sample, nframes, false, true);
}
flush_processor_buffers_locked (nframes);
@@ -980,152 +980,6 @@ Track::adjust_capture_buffering ()
}
}
-#ifdef USE_TRACKS_CODE_FEATURES
-
-/* This is the Tracks version of Track::monitoring_state().
- *
- * Ardour developers: try to flag or fix issues if parts of the libardour API
- * change in ways that invalidate this
- */
-
-MonitorState
-Track::monitoring_state () const
-{
- /* Explicit requests */
-
- if (_monitoring != MonitorInput) {
- return MonitoringInput;
- }
-
- if (_monitoring & MonitorDisk) {
- return MonitoringDisk;
- }
-
- /* This is an implementation of the truth table in doc/monitor_modes.pdf;
- I don't think it's ever going to be too pretty too look at.
- */
-
- // GZ: NOT USED IN TRACKS
- //bool const auto_input = _session.config.get_auto_input ();
- //bool const software_monitor = Config->get_monitoring_model() == SoftwareMonitoring;
- //bool const tape_machine_mode = Config->get_tape_machine_mode ();
-
- bool const roll = _session.transport_rolling ();
- bool const track_rec = _diskstream->record_enabled ();
- bool session_rec = _session.actively_recording ();
-
- if (track_rec) {
-
- if (!session_rec && roll) {
- return MonitoringDisk;
- } else {
- return MonitoringInput;
- }
-
- } else {
-
- if (roll) {
- return MonitoringDisk;
- }
- }
-
- return MonitoringSilence;
-}
-
-#else
-
-/* This is the Ardour/Mixbus version of Track::monitoring_state().
- *
- * Tracks developers: do NOT modify this method under any circumstances.
- */
-
-MonitorState
-Track::monitoring_state () const
-{
- /* Explicit requests */
- MonitorChoice m (_monitoring_control->monitoring_choice());
-
- if (m != MonitorAuto) {
-
- MonitorState ms ((MonitorState) 0);
-
- if (m & MonitorInput) {
- ms = MonitoringInput;
- }
-
- if (m & MonitorDisk) {
- ms = MonitorState (ms | MonitoringDisk);
- }
-
- return ms;
- }
-
- switch (_session.config.get_session_monitoring ()) {
- case MonitorDisk:
- return MonitoringDisk;
- break;
- case MonitorInput:
- return MonitoringInput;
- break;
- default:
- break;
- }
-
- /* This is an implementation of the truth table in doc/monitor_modes.pdf;
- I don't think it's ever going to be too pretty too look at.
- */
-
- bool const roll = _session.transport_rolling ();
- bool const track_rec = _disk_writer->record_enabled ();
- bool const auto_input = _session.config.get_auto_input ();
- bool const software_monitor = Config->get_monitoring_model() == SoftwareMonitoring;
- bool const tape_machine_mode = Config->get_tape_machine_mode ();
- bool session_rec;
-
- /* I suspect that just use actively_recording() is good enough all the
- * time, but just to keep the semantics the same as they were before
- * sept 26th 2012, we differentiate between the cases where punch is
- * enabled and those where it is not.
- *
- * rg: I suspect this is not the case: monitoring may differ
- */
-
- if (_session.config.get_punch_in() || _session.config.get_punch_out() || _session.preroll_record_punch_enabled ()) {
- session_rec = _session.actively_recording ();
- } else {
- session_rec = _session.get_record_enabled();
- }
-
- if (track_rec) {
-
- if (!session_rec && roll && auto_input) {
- return MonitoringDisk;
- } else {
- return software_monitor ? MonitoringInput : MonitoringSilence;
- }
-
- } else {
-
- if (tape_machine_mode) {
-
- return MonitoringDisk;
-
- } else {
-
- if (!roll && auto_input) {
- return software_monitor ? MonitoringInput : MonitoringSilence;
- } else {
- return MonitoringDisk;
- }
-
- }
- }
-
- abort(); /* NOTREACHED */
- return MonitoringSilence;
-}
-
-#endif
void
Track::maybe_declick (BufferSet& bufs, samplecnt_t nframes, int declick)