X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fmtc_slave.cc;h=8ce0722d8b790b5e1f6616050bce3803d141b55a;hb=ef0c4ed0e6907ff7cc0c9f139495619a9f242ff5;hp=99cb66d6305161d1177168821de35186bd1708b4;hpb=f6eeb474824224638dad592e4776823e633b4329;p=ardour.git diff --git a/libs/ardour/mtc_slave.cc b/libs/ardour/mtc_slave.cc index 99cb66d630..8ce0722d8b 100644 --- a/libs/ardour/mtc_slave.cc +++ b/libs/ardour/mtc_slave.cc @@ -56,16 +56,19 @@ MTC_Slave::MTC_Slave (Session& s, MIDI::Port& p) reset_pending = 0; reset_position = false; mtc_frame = 0; + mtc_frame_dll = 0; engine_dll_initstate = 0; busy_guard1 = busy_guard2 = 0; last_mtc_fps_byte = session.get_mtc_timecode_bits (); quarter_frame_duration = (double(session.frames_per_timecode_frame()) / 4.0); - mtc_timecode = timecode_60; // track changes of MTC timecode - a3e_timecode = timecode_60; // track canges of Ardour's timecode + mtc_timecode = session.config.get_timecode_format(); + a3e_timecode = session.config.get_timecode_format(); printed_timecode_warning = false; + session.config.ParameterChanged.connect_same_thread (config_connection, boost::bind (&MTC_Slave::parameter_changed, this, _1)); + parse_timecode_offset(); reset (true); rebind (p); } @@ -73,6 +76,7 @@ MTC_Slave::MTC_Slave (Session& s, MIDI::Port& p) MTC_Slave::~MTC_Slave() { port_connections.drop_connections(); + config_connection.disconnect(); while (busy_guard1 != busy_guard2) { /* make sure MIDI parser is not currently calling any callbacks in here, @@ -101,6 +105,26 @@ MTC_Slave::rebind (MIDI::Port& p) port->parser()->mtc_status.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_status, this, _1)); } +void +MTC_Slave::parse_timecode_offset() { + Timecode::Time offset_tc; + Timecode::parse_timecode_format(session.config.get_slave_timecode_offset(), offset_tc); + offset_tc.rate = session.timecode_frames_per_second(); + offset_tc.drop = session.timecode_drop_frames(); + session.timecode_to_sample(offset_tc, timecode_offset, false, false); + timecode_negative_offset = offset_tc.negative; +} + +void +MTC_Slave::parameter_changed (std::string const & p) +{ + if (p == "slave-timecode-offset" + || p == "timecode-format" + ) { + parse_timecode_offset(); + } +} + bool MTC_Slave::give_slave_full_control_over_transport_speed() const { @@ -130,7 +154,7 @@ MTC_Slave::outside_window (framepos_t pos) const bool MTC_Slave::locked () const { - return port->parser()->mtc_locked(); + return port->parser()->mtc_locked() && last_inbound_frame !=0 && engine_dll_initstate !=0; } bool @@ -221,7 +245,7 @@ MTC_Slave::read_current (SafeTime *st) const void MTC_Slave::init_mtc_dll(framepos_t tme, double qtr) { - omega = 2.0 * M_PI * qtr / double(session.frame_rate()); + omega = 2.0 * M_PI * qtr / 2.0 / double(session.frame_rate()); b = 1.4142135623730950488 * omega; c = omega * omega; @@ -238,32 +262,33 @@ MTC_Slave::update_mtc_qtr (Parser& /*p*/, int which_qtr, framepos_t now) { busy_guard1++; const double qtr_d = quarter_frame_duration; - const framepos_t qtr = rint(qtr_d); - mtc_frame += qtr * transport_direction; + mtc_frame_dll += qtr_d * (double) transport_direction; + mtc_frame = rint(mtc_frame_dll); DEBUG_TRACE (DEBUG::MTC, string_compose ("qtr frame %1 at %2 -> mtc_frame: %3\n", which_qtr, now, mtc_frame)); double mtc_speed = 0; if (first_mtc_timestamp != 0) { /* update MTC DLL and calculate speed */ - const double e = double(transport_direction) * (double(now) - double(current.timestamp) - qtr_d); + const double e = mtc_frame_dll - (double)transport_direction * ((double)now - (double)current.timestamp + t0); t0 = t1; t1 += b * e + e2; e2 += c * e; mtc_speed = (t1 - t0) / qtr_d; DEBUG_TRACE (DEBUG::MTC, string_compose ("qtr frame DLL t0:%1 t1:%2 err:%3 spd:%4 ddt:%5\n", t0, t1, e, mtc_speed, e2 - qtr_d)); - } - current.guard1++; - current.position = mtc_frame; - current.timestamp = now; - current.speed = mtc_speed; - current.guard2++; + current.guard1++; + current.position = mtc_frame; + current.timestamp = now; + current.speed = mtc_speed; + current.guard2++; + + last_inbound_frame = now; + } maybe_reset (); - last_inbound_frame = now; busy_guard2++; } @@ -312,9 +337,14 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full, framepos_t now) can_notify_on_unknown_rate = true; break; case MTC_30_FPS_DROP: - timecode.rate = (30000.0/1001.0); + if (Config->get_timecode_source_2997()) { + tc_format = Timecode::timecode_2997000drop; + timecode.rate = (29970.0/1000.0); + } else { + tc_format = timecode_2997drop; + timecode.rate = (30000.0/1001.0); + } timecode.drop = true; - tc_format = timecode_2997drop; can_notify_on_unknown_rate = true; break; case MTC_30_FPS: @@ -345,10 +375,12 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full, framepos_t now) did_reset_tc_format = true; } if (cur_timecode != tc_format) { - warning << string_compose(_("Session framerate adjusted from %1 TO: MTC's %2."), - Timecode::timecode_format_name(cur_timecode), - Timecode::timecode_format_name(tc_format)) - << endmsg; + if (ceil(Timecode::timecode_to_frames_per_second(cur_timecode)) != ceil(Timecode::timecode_to_frames_per_second(tc_format))) { + warning << string_compose(_("Session framerate adjusted from %1 TO: MTC's %2."), + Timecode::timecode_format_name(cur_timecode), + Timecode::timecode_format_name(tc_format)) + << endmsg; + } } session.config.set_timecode_format (tc_format); } else { @@ -357,10 +389,13 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full, framepos_t now) if (a3e_timecode != cur_timecode) printed_timecode_warning = false; if (cur_timecode != tc_format && ! printed_timecode_warning) { - warning << string_compose(_("Session and MTC framerate mismatch: MTC:%1 Ardour:%2."), - Timecode::timecode_format_name(tc_format), - Timecode::timecode_format_name(cur_timecode)) - << endmsg; + if (ceil(Timecode::timecode_to_frames_per_second(cur_timecode)) != ceil(Timecode::timecode_to_frames_per_second(tc_format))) { + warning << string_compose(_("Session and MTC framerate mismatch: MTC:%1 %2:%3."), + Timecode::timecode_format_name(tc_format), + PROGRAM_NAME, + Timecode::timecode_format_name(cur_timecode)) + << endmsg; + } printed_timecode_warning = true; } } @@ -380,7 +415,7 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full, framepos_t now) Timecode::timecode_to_sample (timecode, mtc_frame, true, false, double(session.frame_rate()), session.config.get_subframes_per_frame(), - session.config.get_timecode_offset_negative(), session.config.get_timecode_offset() + timecode_negative_offset, timecode_offset ); DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC at %1 TC %2 = mtc_frame %3 (from full message ? %4) tc-ratio %5\n", @@ -429,6 +464,7 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full, framepos_t now) if (first_mtc_timestamp == 0 || current.timestamp == 0) { first_mtc_timestamp = now; init_mtc_dll(mtc_frame, qtr); + mtc_frame_dll = mtc_frame; } current.guard1++; current.position = mtc_frame; @@ -528,7 +564,7 @@ MTC_Slave::init_engine_dll (framepos_t pos, framepos_t inc) * But this is only really a problem if the user performs manual * seeks while transport is running and slaved to MTC. */ - oe = 2.0 * M_PI * double(inc/6.0) / double(session.frame_rate()); + oe = 2.0 * M_PI * double(inc) / 2.0 / double(session.frame_rate()); be = 1.4142135623730950488 * oe; ce = oe * oe; @@ -548,15 +584,17 @@ MTC_Slave::speed_and_position (double& speed, framepos_t& pos) //sess_pos -= session.engine().frames_since_cycle_start(); SafeTime last; - framecnt_t elapsed; + frameoffset_t elapsed; + bool engine_dll_reinitialized = false; read_current (&last); /* re-init engine DLL here when state changed (direction, first_mtc_timestamp) */ if (last.timestamp == 0) { engine_dll_initstate = 0; } - else if (engine_dll_initstate != transport_direction) { + else if (engine_dll_initstate != transport_direction && last.speed != 0) { engine_dll_initstate = transport_direction; init_engine_dll(last.position, session.engine().frames_per_cycle()); + engine_dll_reinitialized = true; } if (last.timestamp == 0) { @@ -579,8 +617,7 @@ MTC_Slave::speed_and_position (double& speed, framepos_t& pos) } - - DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC::speed_and_position mtc-tme: %1 mtc-pos: %2\n", last.timestamp, last.position)); + DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC::speed_and_position mtc-tme: %1 mtc-pos: %2 mtc-spd: %3\n", last.timestamp, last.position, last.speed)); DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC::speed_and_position eng-tme: %1 eng-pos: %2\n", now, sess_pos)); double speed_flt = last.speed; ///< MTC speed from MTC-quarter-frame DLL @@ -592,15 +629,13 @@ MTC_Slave::speed_and_position (double& speed, framepos_t& pos) else { /* scale elapsed time by the current MTC speed */ - if (last.timestamp && (now > last.timestamp)) { - elapsed = (framecnt_t) rint (speed_flt * (now - last.timestamp)); - } else { - elapsed = 0; - } - if (give_slave_full_control_over_transport_speed()) { - /* there is a frame-delta engine vs MTC position - * mostly due to quantization and rounding of (speed * nframes) - * thus we use an other DLL.. + elapsed = (framecnt_t) rint (speed_flt * (now - last.timestamp)); + if (give_slave_full_control_over_transport_speed() && !engine_dll_reinitialized) { + /* there is an engine vs MTC position frame-delta. + * This mostly due to quantization and rounding of (speed * nframes) + * but can also due to the session-process not calling + * speed_and_position() every cycle under some circumstances. + * Thus we use an other DLL to align the engine and the MTC */ /* update engine DLL and calculate speed */ @@ -628,11 +663,9 @@ MTC_Slave::speed_and_position (double& speed, framepos_t& pos) queue_reset (false); } -#if 1 - /* provide a 1% deadzone to lock the speed */ - if (fabs(speed - 1.0) <= 0.01) + /* provide a .1% deadzone to lock the speed */ + if (fabs(speed - 1.0) <= 0.001) speed = 1.0; -#endif DEBUG_TRACE (DEBUG::MTC, string_compose ("MTCsync spd: %1 pos: %2 | last-pos: %3 elapsed: %4 delta: %5\n", speed, pos, last.position, elapsed, pos - sess_pos)); @@ -648,7 +681,7 @@ MTC_Slave::apparent_timecode_format () const return mtc_timecode; } -std::string +std::string MTC_Slave::approximate_current_position() const { SafeTime last; @@ -666,15 +699,14 @@ MTC_Slave::approximate_current_position() const std::string MTC_Slave::approximate_current_delta() const { - char delta[24]; + char delta[80]; SafeTime last; read_current (&last); if (last.timestamp == 0 || reset_pending) { snprintf(delta, sizeof(delta), "\u2012\u2012\u2012\u2012"); } else { - // TODO if current_delta > 1 frame -> display timecode. - snprintf(delta, sizeof(delta), "%s%4" PRIi64 " sm", - PLUSMINUS(-current_delta), abs(current_delta)); + snprintf(delta, sizeof(delta), "\u0394%s%s%" PRIi64 "sm", + LEADINGZERO(abs(current_delta)), PLUSMINUS(-current_delta), abs(current_delta)); } return std::string(delta); }