X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fmtc_slave.cc;h=4ca86236b737c113f8587bdffabfad3f30b61d43;hb=9e9cb3bf31a8cbf00ecf43ea0c3acd8b8bb86760;hp=c502cb16a2dc27d86eda49e7cf311f9ea75a34c4;hpb=e374518ca9c4643874eee3877e270eef32d95f18;p=ardour.git diff --git a/libs/ardour/mtc_slave.cc b/libs/ardour/mtc_slave.cc index c502cb16a2..4ca86236b7 100644 --- a/libs/ardour/mtc_slave.cc +++ b/libs/ardour/mtc_slave.cc @@ -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,31 +74,51 @@ MTC_Slave::rebind (MIDI::Port& p) } void -MTC_Slave::update_mtc_qtr (Parser& /*p*/) +MTC_Slave::update_mtc_qtr (Parser& /*p*/, int which_qtr, nframes_t now) { - nframes64_t now = session.engine().frame_time(); - nframes_t qtr; + 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)); - qtr = (long) (session.frames_per_timecode_frame() / 4); - mtc_frame += qtr; - - double speed = compute_apparent_speed (now); + if (qtr_frame_messages_valid_for_time) { - current.guard1++; - current.position = mtc_frame; - current.timestamp = now; - current.speed = speed; - current.guard2++; + 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. + */ - 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 -MTC_Slave::update_mtc_time (const byte *msg, bool was_full) +MTC_Slave::update_mtc_time (const byte *msg, bool was_full, nframes_t now) { - nframes64_t now = session.engine().frame_time(); - Timecode::Time timecode; + /* "now" can be zero if this is called from a context where we do not have or do not want + to use a timestamp indicating when this MTC time was received. + */ + Timecode::Time timecode; + TimecodeFormat tc_format; + bool reset_tc = true; + + DEBUG_TRACE (DEBUG::MTC, string_compose ("full mtc time known at %1, full ? %2\n", now, was_full)); + timecode.hours = msg[3]; timecode.minutes = msg[2]; timecode.seconds = msg[1]; @@ -106,22 +130,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,44 +161,62 @@ 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 */ - current.guard1++; - current.position = mtc_frame; - current.timestamp = now; - current.guard2++; + mtc_frame += (long) (1.75 * session.frames_per_timecode_frame()) + session.worst_output_latency(); - DEBUG_TRACE (DEBUG::MTC, string_compose ("stored TC frame = %1 @ %2, sp = %3\n", mtc_frame, now, speed)); -#endif + if (now) { + double speed = compute_apparent_speed (now); + + current.guard1++; + current.position = mtc_frame; + current.timestamp = now; + current.speed = speed; + current.guard2++; + } } - last_inbound_frame = now; + if (now) { + last_inbound_frame = now; + } } double @@ -179,9 +225,11 @@ MTC_Slave::compute_apparent_speed (nframes64_t now) 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 / %4 - %5\n", - speed, mtc_frame, current.position, 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 */ + accumulator[accumulator_index++] = speed; if (accumulator_index >= accumulator_size) { @@ -219,7 +267,7 @@ MTC_Slave::handle_locate (const MIDI::byte* mmc_tc) mtc[1] = mmc_tc[2]; mtc[0] = mmc_tc[3]; - update_mtc_time (mtc, true); + update_mtc_time (mtc, true, 0); } void @@ -334,7 +382,9 @@ MTC_Slave::speed_and_position (double& speed, nframes64_t& pos) /* scale elapsed time by the current MTC speed */ if (last.timestamp && (now > last.timestamp)) { - elapsed = (nframes_t) floor (speed * (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)); } else { elapsed = 0; /* XXX is this right? */ } @@ -374,4 +424,5 @@ MTC_Slave::reset () current.guard2++; accumulator_index = 0; have_first_accumulated_speed = false; + qtr_frame_messages_valid_for_time = false; }