more changes to try to improve MTC handling even in slightly pathological cases

git-svn-id: svn://localhost/ardour2/branches/3.0@6245 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2009-12-01 13:24:08 +00:00
parent ea08bbe621
commit d2426538ad
5 changed files with 77 additions and 29 deletions

View file

@ -234,6 +234,10 @@ class MTC_Slave : public Slave, public sigc::trackable {
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;
bool did_reset_tc_format;
TimecodeFormat saved_tc_format;
static const int32_t accumulator_size = 128;
double accumulator[accumulator_size];
@ -241,11 +245,12 @@ class MTC_Slave : public Slave, public sigc::trackable {
bool have_first_accumulated_speed;
void reset ();
void update_mtc_qtr (MIDI::Parser&);
void update_mtc_qtr (MIDI::Parser&, int);
void update_mtc_time (const MIDI::byte *, bool);
void update_mtc_status (MIDI::Parser::MTC_Status);
void read_current (SafeTime *) const;
double compute_apparent_speed (nframes64_t);
};
class MIDIClock_Slave : public Slave, public sigc::trackable {

View file

@ -44,7 +44,8 @@ MTC_Slave::MTC_Slave (Session& s, MIDI::Port& p)
: session (s)
{
can_notify_on_unknown_rate = true;
did_reset_tc_format = false;
last_mtc_fps_byte = session.get_mtc_timecode_bits ();
rebind (p);
@ -53,6 +54,9 @@ MTC_Slave::MTC_Slave (Session& s, MIDI::Port& p)
MTC_Slave::~MTC_Slave()
{
if (did_reset_tc_format) {
session.config.set_timecode_format (saved_tc_format);
}
}
void
@ -70,23 +74,36 @@ MTC_Slave::rebind (MIDI::Port& p)
}
void
MTC_Slave::update_mtc_qtr (Parser& /*p*/)
MTC_Slave::update_mtc_qtr (Parser& /*p*/, int which_qtr)
{
nframes64_t now = session.engine().frame_time();
nframes_t qtr;
if (qtr_frame_messages_valid_for_time) {
nframes64_t now = session.engine().frame_time();
qtr = (long) (session.frames_per_timecode_frame() / 4);
mtc_frame += qtr;
double speed = compute_apparent_speed (now);
if (which_qtr != 7) {
current.guard1++;
current.position = mtc_frame;
current.timestamp = now;
current.speed = speed;
current.guard2++;
/* 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.
*/
last_inbound_frame = now;
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;
}
}
void
@ -94,6 +111,8 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full)
{
nframes64_t now = session.engine().frame_time();
Timecode::Time timecode;
TimecodeFormat tc_format;
bool reset_tc = true;
timecode.hours = msg[3];
timecode.minutes = msg[2];
@ -106,22 +125,26 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full)
case MTC_24_FPS:
timecode.rate = 24;
timecode.drop = false;
tc_format = timecode_24;
can_notify_on_unknown_rate = true;
break;
case MTC_25_FPS:
timecode.rate = 25;
timecode.drop = false;
tc_format = timecode_25;
can_notify_on_unknown_rate = true;
break;
case MTC_30_FPS_DROP:
timecode.rate = 30;
timecode.drop = true;
tc_format = timecode_30drop;
can_notify_on_unknown_rate = true;
break;
case MTC_30_FPS:
timecode.rate = 30;
timecode.drop = false;
can_notify_on_unknown_rate = true;
tc_format = timecode_30;
break;
default:
/* throttle error messages about unknown MTC rates */
@ -133,41 +156,55 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full)
}
timecode.rate = session.timecode_frames_per_second();
timecode.drop = session.timecode_drop_frames();
reset_tc = false;
}
session.timecode_to_sample (timecode, mtc_frame, true, false);
if (reset_tc) {
if (!did_reset_tc_format) {
saved_tc_format = session.config.get_timecode_format();
did_reset_tc_format = true;
}
session.config.set_timecode_format (tc_format);
}
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) {
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);
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.
*/
qtr_frame_messages_valid_for_time = true;
session.timecode_to_sample (timecode, mtc_frame, true, false);
/* We received the last quarter frame 7 quarter frames (1.75 mtc
frames) after the instance when the contents of the mtc quarter
frames were decided. Add time to compensate for the elapsed 1.75
frames.
Also compensate for audio latency.
frames. Also compensate for audio latency.
*/
#if 0
mtc_frame += (long) (1.75 * session.frames_per_timecode_frame()) + session.worst_output_latency();
/* leave speed alone here. compute it only as we receive qtr frame messages */
double speed = compute_apparent_speed (now);
current.guard1++;
current.position = mtc_frame;
current.timestamp = now;
current.speed = speed;
current.guard2++;
DEBUG_TRACE (DEBUG::MTC, string_compose ("stored TC frame = %1 @ %2, sp = %3\n", mtc_frame, now, speed));
#endif
}
last_inbound_frame = now;
@ -182,6 +219,8 @@ MTC_Slave::compute_apparent_speed (nframes64_t now)
DEBUG_TRACE (DEBUG::MTC, string_compose ("instantaneous speed = %1 from %2 - %3 / %4 - %5\n",
speed, mtc_frame, current.position, now, current.timestamp));
/* crude low pass filter/smoother for speed */
accumulator[accumulator_index++] = speed;
if (accumulator_index >= accumulator_size) {
@ -374,4 +413,5 @@ MTC_Slave::reset ()
current.guard2++;
accumulator_index = 0;
have_first_accumulated_speed = false;
qtr_frame_messages_valid_for_time = false;
}

View file

@ -147,8 +147,9 @@ Session::timecode_drop_frames() const
break;
default:
cerr << "Editor received unexpected timecode type" << endl;
error << "Editor received unexpected timecode type" << endmsg;
}
return false;
}
void

View file

@ -74,8 +74,8 @@ class Parser : public sigc::trackable {
Signal position;
Signal song;
Signal mtc;
sigc::signal<void,Parser&> mtc_qtr;
Signal mtc;
sigc::signal<void,Parser&,int> mtc_qtr;
sigc::signal<void, Parser &> all_notes_off;
sigc::signal<void, Parser &> tune;

View file

@ -226,7 +226,9 @@ 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;
#endif
switch (which_quarter_frame) {
case 0: // frames LS nibble
@ -275,7 +277,7 @@ Parser::process_mtc_quarter_frame (byte *msg)
}
mtc_qtr (*this); /* EMIT_SIGNAL */
mtc_qtr (*this, which_quarter_frame); /* EMIT_SIGNAL */
// mtc (*this, &msg[1], msglen - 1);