mirror of
https://github.com/Ardour/ardour.git
synced 2026-01-07 22:25:46 +01:00
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:
parent
ea08bbe621
commit
d2426538ad
5 changed files with 77 additions and 29 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue