diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2009-12-01 13:24:08 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2009-12-01 13:24:08 +0000 |
commit | d2426538ad8230e62cf4c8f225e6e974aea9e115 (patch) | |
tree | 19493346dd56436dfe2886c1fbea4ed43aaada93 /libs | |
parent | ea08bbe621c146a0940ce584e2b970dcb7d7c9e2 (diff) |
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
Diffstat (limited to 'libs')
-rw-r--r-- | libs/ardour/ardour/slave.h | 7 | ||||
-rw-r--r-- | libs/ardour/mtc_slave.cc | 88 | ||||
-rw-r--r-- | libs/ardour/session_time.cc | 3 | ||||
-rw-r--r-- | libs/midi++2/midi++/parser.h | 4 | ||||
-rw-r--r-- | libs/midi++2/mtc.cc | 4 |
5 files changed, 77 insertions, 29 deletions
diff --git a/libs/ardour/ardour/slave.h b/libs/ardour/ardour/slave.h index 672d72f7e2..af69348d4e 100644 --- a/libs/ardour/ardour/slave.h +++ b/libs/ardour/ardour/slave.h @@ -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 { diff --git a/libs/ardour/mtc_slave.cc b/libs/ardour/mtc_slave.cc index c502cb16a2..44386b647f 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,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; } diff --git a/libs/ardour/session_time.cc b/libs/ardour/session_time.cc index 1e1ecd3ed9..c913a5cb64 100644 --- a/libs/ardour/session_time.cc +++ b/libs/ardour/session_time.cc @@ -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 diff --git a/libs/midi++2/midi++/parser.h b/libs/midi++2/midi++/parser.h index 5baa3af4b6..ea89076225 100644 --- a/libs/midi++2/midi++/parser.h +++ b/libs/midi++2/midi++/parser.h @@ -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; diff --git a/libs/midi++2/mtc.cc b/libs/midi++2/mtc.cc index da85aa11fd..bd3205a8c1 100644 --- a/libs/midi++2/mtc.cc +++ b/libs/midi++2/mtc.cc @@ -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); |