summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/appleutility/wscript4
-rw-r--r--libs/ardour/ardour/session.h18
-rw-r--r--libs/ardour/ardour/slave.h58
-rw-r--r--libs/ardour/audioengine.cc18
-rw-r--r--libs/ardour/enums.cc16
-rw-r--r--libs/ardour/mtc_slave.cc225
-rw-r--r--libs/ardour/session_midi.cc2
-rw-r--r--libs/ardour/session_process.cc111
-rw-r--r--libs/ardour/session_state.cc2
-rw-r--r--libs/ardour/wscript1
-rw-r--r--libs/midi++2/midi++/parser.h6
-rw-r--r--libs/midi++2/mtc.cc6
12 files changed, 261 insertions, 206 deletions
diff --git a/libs/appleutility/wscript b/libs/appleutility/wscript
index 27dc1b9d26..87b713a0dc 100644
--- a/libs/appleutility/wscript
+++ b/libs/appleutility/wscript
@@ -28,7 +28,7 @@ def configure(conf):
def build(bld):
obj = bld.new_task_gen('cxx', 'shlib',
- uselib = 'COREAUDIO CORESERVICES COREFOUNDATION AUDIOTOOLBOX AUDIOUNITS OSX GTKOSX')
+ uselib = 'COREAUDIO CORESERVICES COREFOUNDATION AUDIOTOOLBOX AUDIOUNITS OSX GTKOSX')
obj.source = libappleutility_sources
obj.export_incdirs = ['.']
obj.includes = ['.']
@@ -41,4 +41,4 @@ def shutdown():
autowaf.shutdown()
def i18n(bld):
- pass \ No newline at end of file
+ pass
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index a3505ec587..4f0acc9381 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -986,6 +986,13 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
PostTransportClearSubstate = 0x80000
};
+ enum SlaveState {
+ Stopped,
+ Waiting,
+ Running
+ };
+
+ SlaveState slave_state() const { return _slave_state; }
protected:
friend class AudioEngine;
@@ -1088,20 +1095,13 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
int average_dir;
bool have_first_delta_accumulator;
- enum SlaveState {
- Stopped,
- Waiting,
- Running
- };
-
- SlaveState slave_state;
+ SlaveState _slave_state;
nframes_t slave_wait_end;
void reset_slave_state ();
bool follow_slave (nframes_t);
void calculate_moving_average_of_slave_delta(int dir, nframes_t this_delta);
- void track_slave_state(float slave_speed, nframes_t slave_transport_frame,
- nframes_t this_delta, bool starting);
+ void track_slave_state(float slave_speed, nframes_t slave_transport_frame, nframes_t this_delta);
void follow_slave_silently(nframes_t nframes, float slave_speed);
void use_sync_source (SyncSource);
diff --git a/libs/ardour/ardour/slave.h b/libs/ardour/ardour/slave.h
index 16e11097ea..dae0d80d10 100644
--- a/libs/ardour/ardour/slave.h
+++ b/libs/ardour/ardour/slave.h
@@ -29,6 +29,8 @@
#include "midi++/parser.h"
#include "midi++/types.h"
+class PIController;
+
namespace MIDI {
class Port;
}
@@ -140,12 +142,19 @@ class Slave {
virtual nframes_t resolution() const = 0;
/**
- * @return - when returning true, ARDOUR will wait for one second before transport
+ * @return - when returning true, ARDOUR will wait for seekahead_distance() before transport
* starts rolling
*/
virtual bool requires_seekahead () const = 0;
/**
+ * @return the number of frames that this slave wants to seek ahead. Relevant
+ * only if @func requires_seekahead() returns true.
+ */
+
+ virtual nframes64_t seekahead_distance() const { return 0; }
+
+ /**
* @return - when returning true, ARDOUR will use transport speed 1.0 no matter what
* the slave returns
*/
@@ -222,35 +231,40 @@ class MTC_Slave : public Slave, public sigc::trackable {
nframes_t resolution() const;
bool requires_seekahead () const { return true; }
+ nframes64_t seekahead_distance() const;
+ bool give_slave_full_control_over_transport_speed() const;
private:
Session& session;
MIDI::Port* port;
std::vector<sigc::connection> connections;
bool can_notify_on_unknown_rate;
-
+ PIController* pic;
+
SafeTime current;
- double instantaneous_speed;
nframes_t mtc_frame; /* current time */
nframes_t last_inbound_frame; /* when we got it; audio clocked */
MIDI::byte last_mtc_fps_byte;
- bool qtr_frame_messages_valid_for_time;
-
+ nframes64_t window_begin;
+ nframes64_t window_end;
+ nframes64_t last_mtc_timestamp;
+ nframes64_t last_mtc_frame;
bool did_reset_tc_format;
TimecodeFormat saved_tc_format;
-
- static const int32_t accumulator_size = 128;
- double accumulator[accumulator_size];
- int32_t accumulator_index;
- bool have_first_accumulated_speed;
+ size_t speed_accumulator_size;
+ double* speed_accumulator;
+ size_t speed_accumulator_cnt;
+ bool have_first_speed_accumulator;
+ double average_speed;
void reset ();
void update_mtc_qtr (MIDI::Parser&, int, nframes_t);
void update_mtc_time (const MIDI::byte *, bool, nframes_t);
- void update_mtc_status (MIDI::Parser::MTC_Status);
+ void update_mtc_status (MIDI::MTC_Status);
void read_current (SafeTime *) const;
- double compute_apparent_speed (nframes64_t);
-
+ void reset_window (nframes64_t);
+ bool outside_window (nframes64_t) const;
+ void process_apparent_speed (double);
};
class MIDIClock_Slave : public Slave, public sigc::trackable {
@@ -337,24 +351,6 @@ class MIDIClock_Slave : public Slave, public sigc::trackable {
bool _starting;
};
-class ADAT_Slave : public Slave
-{
- public:
- ADAT_Slave () {}
- ~ADAT_Slave () {}
-
- bool speed_and_position (double& speed, nframes64_t& pos) {
- speed = 0;
- pos = 0;
- return false;
- }
-
- bool locked() const { return false; }
- bool ok() const { return false; }
- nframes_t resolution() const { return 1; }
- bool requires_seekahead () const { return true; }
-};
-
class JACK_Slave : public Slave
{
public:
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index 2e5aea9047..2f344eb8ba 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -136,9 +136,13 @@ _thread_init_callback (void * /*arg*/)
*/
PBD::notify_gui_about_thread_creation (pthread_self(), X_("Audioengine"), 4096);
-#ifdef WITH_JACK_MIDI
MIDI::JACK_MidiPort::set_process_thread (pthread_self());
-#endif // WITH_JACK_MIDI
+}
+
+static void
+ardour_jack_error (const char* msg)
+{
+ error << "JACK: " << msg << endmsg;
}
int
@@ -188,6 +192,8 @@ AudioEngine::start ()
jack_set_timebase_callback (_priv_jack, 0, _jack_timebase_callback, this);
}
+ jack_set_error_function (ardour_jack_error);
+
if (jack_activate (_priv_jack) == 0) {
_running = true;
_has_run = true;
@@ -1121,12 +1127,6 @@ AudioEngine::remove_all_ports ()
ports.flush ();
}
-static void
-ardour_jack_error (const char* msg)
-{
- error << "JACK: " << msg << endmsg;
-}
-
int
AudioEngine::connect_to_jack (string client_name)
{
@@ -1148,8 +1148,6 @@ AudioEngine::connect_to_jack (string client_name)
jack_client_name = jack_get_client_name (_priv_jack);
}
- jack_set_error_function (ardour_jack_error);
-
return 0;
}
diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc
index 870c60eec7..4b82950f3e 100644
--- a/libs/ardour/enums.cc
+++ b/libs/ardour/enums.cc
@@ -18,6 +18,7 @@
*/
#include "pbd/enumwriter.h"
+#include "midi++/types.h"
#include "ardour/audiofilesource.h"
#include "ardour/audioregion.h"
@@ -40,6 +41,7 @@
using namespace std;
using namespace PBD;
using namespace ARDOUR;
+using namespace MIDI;
void
setup_enum_writer ()
@@ -115,7 +117,9 @@ setup_enum_writer ()
WaveformShape _WaveformShape;
QuantizeType _QuantizeType;
Session::PostTransportWork _Session_PostTransportWork;
-
+ Session::SlaveState _Session_SlaveState;
+ MTC_Status _MIDI_MTC_Status;
+
#define REGISTER(e) enum_writer->register_distinct (typeid(e).name(), i, s); i.clear(); s.clear()
#define REGISTER_BITS(e) enum_writer->register_bits (typeid(e).name(), i, s); i.clear(); s.clear()
#define REGISTER_ENUM(e) i.push_back (e); s.push_back (#e)
@@ -305,6 +309,16 @@ setup_enum_writer ()
REGISTER_CLASS_ENUM (Session::Event, AutoLoop);
REGISTER (_Session_Event_Type);
+ REGISTER_CLASS_ENUM (Session, Stopped);
+ REGISTER_CLASS_ENUM (Session, Waiting);
+ REGISTER_CLASS_ENUM (Session, Running);
+ REGISTER (_Session_SlaveState);
+
+ REGISTER_ENUM (MTC_Stopped);
+ REGISTER_ENUM (MTC_Forward);
+ REGISTER_ENUM (MTC_Backward);
+ REGISTER (_MIDI_MTC_Status);
+
REGISTER_CLASS_ENUM (Session, PostTransportStop);
REGISTER_CLASS_ENUM (Session, PostTransportDisableRecord);
REGISTER_CLASS_ENUM (Session, PostTransportPosition);
diff --git a/libs/ardour/mtc_slave.cc b/libs/ardour/mtc_slave.cc
index 4ca86236b7..9e566367bc 100644
--- a/libs/ardour/mtc_slave.cc
+++ b/libs/ardour/mtc_slave.cc
@@ -22,6 +22,7 @@
#include <sys/types.h>
#include <unistd.h>
#include "pbd/error.h"
+#include "pbd/enumwriter.h"
#include "pbd/failed_constructor.h"
#include "pbd/pthread_utils.h"
@@ -30,7 +31,7 @@
#include "ardour/slave.h"
#include "ardour/session.h"
#include "ardour/audioengine.h"
-#include "ardour/cycles.h"
+#include "ardour/pi_controller.h"
#include "i18n.h"
@@ -45,8 +46,14 @@ MTC_Slave::MTC_Slave (Session& s, MIDI::Port& p)
{
can_notify_on_unknown_rate = true;
did_reset_tc_format = false;
+
+ pic = new PIController (1.0, 8);
last_mtc_fps_byte = session.get_mtc_timecode_bits ();
+ mtc_frame = 0;
+
+ speed_accumulator_size = 16;
+ speed_accumulator = new double[speed_accumulator_size];
rebind (p);
reset ();
@@ -57,6 +64,15 @@ MTC_Slave::~MTC_Slave()
if (did_reset_tc_format) {
session.config.set_timecode_format (saved_tc_format);
}
+ delete pic;
+ delete [] speed_accumulator;
+}
+
+bool
+MTC_Slave::give_slave_full_control_over_transport_speed() const
+{
+ return true; // for PiC control */
+ // return false; // for Session-level computed varispeed
}
void
@@ -68,6 +84,8 @@ MTC_Slave::rebind (MIDI::Port& p)
port = &p;
+ cerr << "Bind to port MTC messages\n";
+
connections.push_back (port->input()->mtc_time.connect (mem_fun (*this, &MTC_Slave::update_mtc_time)));
connections.push_back (port->input()->mtc_qtr.connect (mem_fun (*this, &MTC_Slave::update_mtc_qtr)));
connections.push_back (port->input()->mtc_status.connect (mem_fun (*this, &MTC_Slave::update_mtc_status)));
@@ -76,34 +94,8 @@ MTC_Slave::rebind (MIDI::Port& p)
void
MTC_Slave::update_mtc_qtr (Parser& /*p*/, int which_qtr, nframes_t now)
{
- DEBUG_TRACE (DEBUG::MTC, string_compose ("qtr frame %1 at %2, valid-for-time? %3\n", which_qtr, now, qtr_frame_messages_valid_for_time));
-
- if (qtr_frame_messages_valid_for_time) {
-
- if (which_qtr != 7) {
-
- /* leave position and speed updates for the last
- qtr frame message of the 8 to be taken
- care of in update_mtc_time(), invoked
- by the Parser right after this.
- */
-
- nframes_t qtr;
-
- qtr = (long) (session.frames_per_timecode_frame() / 4);
- mtc_frame += qtr;
-
- double speed = compute_apparent_speed (now);
-
- current.guard1++;
- current.position = mtc_frame;
- current.timestamp = now;
- current.speed = speed;
- current.guard2++;
- }
-
- last_inbound_frame = now;
- }
+ DEBUG_TRACE (DEBUG::MTC, string_compose ("qtr frame %1 at %2\n", which_qtr, now));
+ last_inbound_frame = now;
}
void
@@ -116,7 +108,8 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full, nframes_t now)
Timecode::Time timecode;
TimecodeFormat tc_format;
bool reset_tc = true;
-
+ nframes64_t window_root = -1;
+
DEBUG_TRACE (DEBUG::MTC, string_compose ("full mtc time known at %1, full ? %2\n", now, was_full));
timecode.hours = msg[3];
@@ -175,24 +168,28 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full, nframes_t now)
DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC time timestamp = %1 TC %2 = frame %3 (from full message ? %4)\n",
now, timecode, mtc_frame, was_full));
- if (was_full) {
+ if (was_full || outside_window (mtc_frame)) {
session.timecode_to_sample (timecode, mtc_frame, true, false);
session.request_locate (mtc_frame, false);
session.request_transport_speed (0);
- update_mtc_status (MIDI::Parser::MTC_Stopped);
-
+ update_mtc_status (MIDI::MTC_Stopped);
+ window_root = mtc_frame;
+
reset ();
} else {
-
/* we've had the first set of 8 qtr frame messages, determine position
- and allow continuing qtr frame messages to provide position
- and speed information.
+ and allow continuing qtr frame messages to provide position
+ and speed information.
*/
- qtr_frame_messages_valid_for_time = true;
+ /* do a careful conversion of the timecode value to a position
+ so that we take drop/nondrop and all that nonsense into
+ consideration.
+ */
+
session.timecode_to_sample (timecode, mtc_frame, true, false);
/* We received the last quarter frame 7 quarter frames (1.75 mtc
@@ -203,56 +200,84 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full, nframes_t now)
mtc_frame += (long) (1.75 * session.frames_per_timecode_frame()) + session.worst_output_latency();
+
if (now) {
- double speed = compute_apparent_speed (now);
-
+
+ if (last_mtc_timestamp == 0) {
+
+ last_mtc_timestamp = now;
+ last_mtc_frame = mtc_frame;
+
+ } else {
+
+ if (give_slave_full_control_over_transport_speed()) {
+ /* PIC
+ *
+ * its not the average, but we will assign it to current.speed below
+ */
+
+ average_speed = pic->get_ratio (session.audible_frame() - mtc_frame);
+
+ } else {
+
+ /* Non-PiC
+ */
+
+ nframes64_t time_delta = (now - last_mtc_timestamp);
+
+ if (time_delta != 0) {
+ double apparent_speed = (mtc_frame - last_mtc_frame) / (double) (time_delta);
+
+ process_apparent_speed (apparent_speed);
+ DEBUG_TRACE (DEBUG::Slave, string_compose ("apparent speed was %1 average is now %2\n", apparent_speed, average_speed));
+ } else {
+ DEBUG_TRACE (DEBUG::Slave, string_compose ("no apparent calc, average is %1\n", average_speed));
+ }
+
+ /* every second, recalibrate the starting point for the speed measurement */
+ if (mtc_frame - last_mtc_frame > session.frame_rate()) {
+ last_mtc_timestamp = now;
+ last_mtc_frame = mtc_frame;
+ }
+ }
+ }
+
current.guard1++;
current.position = mtc_frame;
current.timestamp = now;
- current.speed = speed;
+ current.speed = average_speed;
current.guard2++;
+ window_root = mtc_frame;
}
}
if (now) {
last_inbound_frame = now;
}
+
+ if (window_root >= 0) {
+ reset_window (window_root);
+ }
}
-double
-MTC_Slave::compute_apparent_speed (nframes64_t now)
+void
+MTC_Slave::process_apparent_speed (double this_speed)
{
- if (current.timestamp != 0) {
-
- double speed = (double) ((mtc_frame - current.position) / (double) (now - current.timestamp));
- DEBUG_TRACE (DEBUG::MTC, string_compose ("instantaneous speed = %1 from %2 / %3\n",
- speed, mtc_frame - current.position, now - current.timestamp));
-
- /* crude low pass filter/smoother for speed */
+ DEBUG_TRACE (DEBUG::MTC, string_compose ("speed cnt %1 sz %2 have %3\n", speed_accumulator_cnt, speed_accumulator_size, have_first_speed_accumulator));
- accumulator[accumulator_index++] = speed;
-
- if (accumulator_index >= accumulator_size) {
- have_first_accumulated_speed = true;
- accumulator_index = 0;
- }
-
- if (have_first_accumulated_speed) {
- double total = 0;
-
- for (int32_t i = 0; i < accumulator_size; ++i) {
- total += accumulator[i];
- }
-
- speed = total / accumulator_size;
- DEBUG_TRACE (DEBUG::MTC, string_compose ("speed smoothed to %1\n", speed));
- }
+ if (speed_accumulator_cnt >= speed_accumulator_size) {
+ have_first_speed_accumulator = true;
+ speed_accumulator_cnt = 0;
+ }
- return speed;
-
- } else {
-
- return 0;
+ speed_accumulator[speed_accumulator_cnt++] = this_speed;
+
+ if (have_first_speed_accumulator) {
+ average_speed = 0.0;
+ for (size_t i = 0; i < speed_accumulator_size; ++i) {
+ average_speed += speed_accumulator[i];
+ }
+ average_speed /= speed_accumulator_size;
}
}
@@ -271,16 +296,16 @@ MTC_Slave::handle_locate (const MIDI::byte* mmc_tc)
}
void
-MTC_Slave::update_mtc_status (MIDI::Parser::MTC_Status status)
+MTC_Slave::update_mtc_status (MIDI::MTC_Status status)
{
/* XXX !!! thread safety ... called from MIDI I/O context
and process() context (via ::speed_and_position())
*/
+
+ DEBUG_TRACE (DEBUG::MTC, string_compose ("new MTC status %1\n", enum_2_string (status)));
switch (status) {
case MTC_Stopped:
- mtc_frame = 0;
-
current.guard1++;
current.position = mtc_frame;
current.timestamp = 0;
@@ -290,27 +315,22 @@ MTC_Slave::update_mtc_status (MIDI::Parser::MTC_Status status)
break;
case MTC_Forward:
- mtc_frame = 0;
-
current.guard1++;
current.position = mtc_frame;
current.timestamp = 0;
current.speed = 0;
current.guard2++;
-
break;
case MTC_Backward:
- mtc_frame = 0;
-
current.guard1++;
current.position = mtc_frame;
current.timestamp = 0;
current.speed = 0;
current.guard2++;
-
break;
}
+
}
void
@@ -365,7 +385,7 @@ MTC_Slave::speed_and_position (double& speed, nframes64_t& pos)
pos = last.position;
session.request_locate (pos, false);
session.request_transport_speed (0);
- update_mtc_status (MIDI::Parser::MTC_Stopped);
+ update_mtc_status (MIDI::MTC_Stopped);
reset();
DEBUG_TRACE (DEBUG::MTC, "MTC not seen for 1/4 second - reset\n");
return false;
@@ -384,7 +404,7 @@ MTC_Slave::speed_and_position (double& speed, nframes64_t& pos)
if (last.timestamp && (now > last.timestamp)) {
elapsed = (nframes_t) floor (last.speed * (now - last.timestamp));
DEBUG_TRACE (DEBUG::MTC, string_compose ("last timecode received @ %1, now = %2, elapsed frames = %3 w/speed= %4\n",
- last.timestamp, now, elapsed, speed));
+ last.timestamp, now, elapsed, last.speed));
} else {
elapsed = 0; /* XXX is this right? */
}
@@ -422,7 +442,42 @@ MTC_Slave::reset ()
current.timestamp = 0;
current.speed = 0;
current.guard2++;
- accumulator_index = 0;
- have_first_accumulated_speed = false;
- qtr_frame_messages_valid_for_time = false;
+
+ window_begin = 0;
+ window_end = 0;
+ last_mtc_frame = 0;
+ last_mtc_timestamp = 0;
+
+ average_speed = 0;
+ have_first_speed_accumulator = false;
+ speed_accumulator_cnt = 0;
+
+ pic->out_of_bounds();
+}
+
+void
+MTC_Slave::reset_window (nframes64_t root)
+{
+ window_begin = root;
+
+ if (session.slave_state() == Session::Running) {
+ window_end = root + (session.frames_per_timecode_frame() * 2);
+ } else {
+ window_end = root + seekahead_distance ();
+ }
+
+ DEBUG_TRACE (DEBUG::MTC, string_compose ("legal MTC window now %1 .. %2\n", window_begin, window_end));
+}
+
+nframes64_t
+MTC_Slave::seekahead_distance () const
+{
+ /* 1 second */
+ return session.frame_rate();
+}
+
+bool
+MTC_Slave::outside_window (nframes64_t pos) const
+{
+ return ((pos < window_begin) || (pos > window_end));
}
diff --git a/libs/ardour/session_midi.cc b/libs/ardour/session_midi.cc
index d205cc1ca8..b05cfc83a2 100644
--- a/libs/ardour/session_midi.cc
+++ b/libs/ardour/session_midi.cc
@@ -1261,7 +1261,7 @@ Session::midi_thread_work ()
}
if (pfd[p].revents & POLLIN) {
- DEBUG_TRACE (DEBUG::MidiIO, string_compose ("MIDI fd # %1 has data ready\n", p));
+ DEBUG_TRACE (DEBUG::MidiIO, string_compose ("MIDI fd # %1 has data ready @ %2\n", p, now));
fds_ready++;
ports[p]->parse (now);
}
diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc
index e270a7c3ec..4142490af6 100644
--- a/libs/ardour/session_process.cc
+++ b/libs/ardour/session_process.cc
@@ -461,7 +461,7 @@ Session::reset_slave_state ()
average_slave_delta = 1800;
delta_accumulator_cnt = 0;
have_first_delta_accumulator = false;
- slave_state = Stopped;
+ _slave_state = Stopped;
}
bool
@@ -483,7 +483,6 @@ Session::follow_slave (nframes_t nframes)
nframes64_t slave_transport_frame;
nframes_t this_delta;
int dir;
- bool starting;
if (!_slave->ok()) {
stop_transport ();
@@ -493,7 +492,7 @@ Session::follow_slave (nframes_t nframes)
_slave->speed_and_position (slave_speed, slave_transport_frame);
- DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave @ %2 speed %1\n", slave_speed, slave_transport_frame));
+ DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave position %1 speed %2\n", slave_transport_frame, slave_speed));
if (!_slave->locked()) {
DEBUG_TRACE (DEBUG::Slave, "slave not locked\n");
@@ -508,7 +507,7 @@ Session::follow_slave (nframes_t nframes)
dir = -1;
}
- if ((starting = _slave->starting())) {
+ if (_slave->starting()) {
slave_speed = 0.0f;
}
@@ -524,21 +523,23 @@ Session::follow_slave (nframes_t nframes)
} else {
- /* TC source is able to drift relative to us (slave)
- so we need to keep track of the drift and adjust
- our speed to remain locked.
+ /* if we are chasing and the average delta between us and the
+ master gets too big, we want to switch to silent
+ motion. so keep track of that here.
*/
- calculate_moving_average_of_slave_delta(dir, this_delta);
+ if (_slave_state == Running) {
+ calculate_moving_average_of_slave_delta(dir, this_delta);
+ }
}
- track_slave_state (slave_speed, slave_transport_frame, this_delta, starting);
+ track_slave_state (slave_speed, slave_transport_frame, this_delta);
- DEBUG_TRACE (DEBUG::Slave, string_compose ("slave state %1 @ %2 speed %3 cur delta %4 starting %5\n",
- slave_state, slave_transport_frame, slave_speed, this_delta, starting));
+ DEBUG_TRACE (DEBUG::Slave, string_compose ("slave state %1 @ %2 speed %3 cur delta %4 avg delta %5\n",
+ _slave_state, slave_transport_frame, slave_speed, this_delta, average_slave_delta));
- if (slave_state == Running && !_slave->is_always_synced() && !config.get_timecode_source_is_synced()) {
+ if (_slave_state == Running && !_slave->is_always_synced() && !config.get_timecode_source_is_synced()) {
if (_transport_speed != 0.0f) {
@@ -548,7 +549,6 @@ Session::follow_slave (nframes_t nframes)
float delta;
-#ifdef USE_MOVING_AVERAGE_OF_SLAVE
if (average_slave_delta == 0) {
delta = this_delta;
delta *= dir;
@@ -556,52 +556,38 @@ Session::follow_slave (nframes_t nframes)
delta = average_slave_delta;
delta *= average_dir;
}
-#else
- delta = this_delta;
- delta *= dir;
-#endif
#ifndef NDEBUG
- if (slave_speed != 0.0) {
- DEBUG_TRACE (DEBUG::Slave, string_compose ("delta = %1 speed = %2 ts = %3 M@%4 S@%5 avgdelta %6\n",
- (int) (dir * this_delta),
- slave_speed,
- _transport_speed,
- _transport_frame,
- slave_transport_frame,
- _transport_frame,
- average_slave_delta));
- }
+ if (slave_speed != 0.0) {
+ DEBUG_TRACE (DEBUG::Slave, string_compose ("delta = %1 speed = %2 ts = %3 M@%4 S@%5 avgdelta %6\n",
+ (int) (dir * this_delta),
+ slave_speed,
+ _transport_speed,
+ _transport_frame,
+ slave_transport_frame,
+ average_slave_delta));
+ }
#endif
- if (fabs(delta) > 2048) {
- nframes64_t jump_to = slave_transport_frame + lrintf (_current_frame_rate/5.0f);
- /* too far off, so locate and keep rolling */
- DEBUG_TRACE (DEBUG::Slave, string_compose ("slave delta %1 is too big, locate to %2\n",
- delta, jump_to));
- request_locate (jump_to, true);
- return false;
+
+ if (_slave->give_slave_full_control_over_transport_speed()) {
+ set_transport_speed (slave_speed, false, false);
} else {
float adjusted_speed = slave_speed + (delta / float(_current_frame_rate));
-
- if (_slave->give_slave_full_control_over_transport_speed()) {
- request_transport_speed (slave_speed);
- } else {
- request_transport_speed (adjusted_speed);
- DEBUG_TRACE (DEBUG::Slave, string_compose ("adjust using %1 towards %2 ratio %3 current %4 slave @ %5\n",
- delta, adjusted_speed, adjusted_speed/slave_speed, _transport_speed,
- slave_speed));
- }
+ request_transport_speed (adjusted_speed);
+ DEBUG_TRACE (DEBUG::Slave, string_compose ("adjust using %1 towards %2 ratio %3 current %4 slave @ %5\n",
+ delta, adjusted_speed, adjusted_speed/slave_speed, _transport_speed,
+ slave_speed));
}
- if (abs(average_slave_delta) > (long) _slave->resolution()) {
- cerr << "average slave delta greater than slave resolution, going to silent motion\n";
+ if (abs(average_slave_delta) > _slave->resolution()) {
+ cerr << "average slave delta greater than slave resolution (" << _slave->resolution() << "), going to silent motion\n";
goto silent_motion;
}
}
}
- if (!starting && !non_realtime_work_pending()) {
+ if (_slave_state == Running && !non_realtime_work_pending()) {
/* speed is set, we're locked, and good to go */
return true;
}
@@ -645,24 +631,24 @@ Session::calculate_moving_average_of_slave_delta(int dir, nframes_t this_delta)
}
void
-Session::track_slave_state (float slave_speed, nframes_t slave_transport_frame, nframes_t this_delta, bool starting)
+Session::track_slave_state (float slave_speed, nframes_t slave_transport_frame, nframes_t this_delta)
{
if (slave_speed != 0.0f) {
/* slave is running */
- switch (slave_state) {
+ switch (_slave_state) {
case Stopped:
if (_slave->requires_seekahead()) {
- slave_wait_end = slave_transport_frame + _current_frame_rate;
+ slave_wait_end = slave_transport_frame + _slave->seekahead_distance ();
DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, but running, requires seekahead to %1\n", slave_wait_end));
+ /* we can call locate() here because we are in process context */
locate (slave_wait_end, false, false);
- slave_state = Waiting;
- starting = true;
+ _slave_state = Waiting;
} else {
- slave_state = Running;
+ _slave_state = Running;
Location* al = _locations.auto_loop_location();
@@ -678,13 +664,24 @@ Session::track_slave_state (float slave_speed, nframes_t slave_transport_frame,
break;
case Waiting:
+ default:
+ break;
+ }
+
+ if (_slave_state == Waiting) {
+
DEBUG_TRACE (DEBUG::Slave, string_compose ("slave waiting at %1\n", slave_transport_frame));
if (slave_transport_frame >= slave_wait_end) {
DEBUG_TRACE (DEBUG::Slave, string_compose ("slave start at %1 vs %2\n", slave_transport_frame, _transport_frame));
- slave_state = Running;
+ _slave_state = Running;
+
+ /* now perform a "micro-seek" within the disk buffers to realign ourselves
+ precisely with the master.
+ */
+
bool ok = true;
nframes_t frame_delta = slave_transport_frame - _transport_frame;
@@ -713,13 +710,9 @@ Session::track_slave_state (float slave_speed, nframes_t slave_transport_frame,
average_slave_delta = 0L;
this_delta = 0;
}
- break;
-
- default:
- break;
}
- if (slave_state == Running && _transport_speed == 0.0f) {
+ if (_slave_state == Running && _transport_speed == 0.0f) {
DEBUG_TRACE (DEBUG::Slave, "slave starts transport\n");
start_transport ();
}
@@ -738,7 +731,7 @@ Session::track_slave_state (float slave_speed, nframes_t slave_transport_frame,
force_locate (slave_transport_frame, false);
}
- slave_state = Stopped;
+ _slave_state = Stopped;
}
}
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index 86a317d1d1..bcc3afbb05 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -263,7 +263,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
average_slave_delta = 1800; // !!! why 1800 ????
have_first_delta_accumulator = false;
delta_accumulator_cnt = 0;
- slave_state = Stopped;
+ _slave_state = Stopped;
_engine.GraphReordered.connect (mem_fun (*this, &Session::graph_reordered));
diff --git a/libs/ardour/wscript b/libs/ardour/wscript
index 48cd6ccb6f..bf850ebeab 100644
--- a/libs/ardour/wscript
+++ b/libs/ardour/wscript
@@ -132,6 +132,7 @@ libardour_sources = [
'onset_detector.cc',
'panner.cc',
'pcm_utils.cc',
+ 'pi_controller.cc',
'playlist.cc',
'playlist_factory.cc',
'plugin.cc',
diff --git a/libs/midi++2/midi++/parser.h b/libs/midi++2/midi++/parser.h
index b8364cc025..365f2fb46a 100644
--- a/libs/midi++2/midi++/parser.h
+++ b/libs/midi++2/midi++/parser.h
@@ -116,12 +116,6 @@ class Parser : public sigc::trackable {
/* MTC */
- enum MTC_Status {
- MTC_Stopped = 0,
- MTC_Forward,
- MTC_Backward
- };
-
MTC_FPS mtc_fps() const { return _mtc_fps; }
MTC_Status mtc_running() const { return _mtc_running; }
const byte *mtc_current() const { return _mtc_time; }
diff --git a/libs/midi++2/mtc.cc b/libs/midi++2/mtc.cc
index 74b528e5e3..a49f469d2b 100644
--- a/libs/midi++2/mtc.cc
+++ b/libs/midi++2/mtc.cc
@@ -226,7 +226,7 @@ Parser::process_mtc_quarter_frame (byte *msg)
/* time code is looking good */
#ifdef DEBUG_MTC
- cerr << "for quarter frame " << which_quarter_frame << " byte = " << hex << (int) msg[1] << dec << endl;
+ // cerr << "for quarter frame " << which_quarter_frame << " byte = " << hex << (int) msg[1] << dec << endl;
#endif
switch (which_quarter_frame) {
@@ -276,6 +276,10 @@ Parser::process_mtc_quarter_frame (byte *msg)
}
+#ifdef DEBUG_MTC
+ cerr << "Emit MTC Qtr\n";
+#endif
+
mtc_qtr (*this, which_quarter_frame, _timestamp); /* EMIT_SIGNAL */
// mtc (*this, &msg[1], msglen - 1);