diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2009-12-01 01:08:56 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2009-12-01 01:08:56 +0000 |
commit | 2ad2792bcbdaa66d734562c207e23cd3113591bc (patch) | |
tree | d0e36457f7e416d6fd8d71f867b1b6c32daaf30e | |
parent | 63f5e14e018f8b5cec922767b31eaaca611aee26 (diff) |
rework MTC slave so that speed is computed in the MIDI I/O context, not process() context
git-svn-id: svn://localhost/ardour2/branches/3.0@6233 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r-- | libs/ardour/ardour/slave.h | 30 | ||||
-rw-r--r-- | libs/ardour/mtc_slave.cc | 95 | ||||
-rw-r--r-- | libs/ardour/session_midi.cc | 18 |
3 files changed, 69 insertions, 74 deletions
diff --git a/libs/ardour/ardour/slave.h b/libs/ardour/ardour/slave.h index 9036c97a27..86889006f2 100644 --- a/libs/ardour/ardour/slave.h +++ b/libs/ardour/ardour/slave.h @@ -193,16 +193,19 @@ class SlaveSessionProxy : public ISlaveSessionProxy { }; struct SafeTime { - int guard1; - nframes_t position; - nframes_t timestamp; - int guard2; - - SafeTime() { - guard1 = 0; - guard2 = 0; - timestamp = 0; - } + volatile int guard1; + nframes64_t position; + nframes64_t timestamp; + double speed; + volatile int guard2; + + SafeTime() { + guard1 = 0; + position = 0; + timestamp = 0; + speed = 0; + guard2 = 0; + } }; class MTC_Slave : public Slave, public sigc::trackable { @@ -225,16 +228,13 @@ class MTC_Slave : public Slave, public sigc::trackable { MIDI::Port* port; std::vector<sigc::connection> connections; bool can_notify_on_unknown_rate; - + SafeTime current; + double instantaneous_speed; nframes_t mtc_frame; /* current time */ nframes_t last_inbound_frame; /* when we got it; audio clocked */ MIDI::byte last_mtc_fps_byte; - double mtc_speed; - nframes_t first_mtc_frame; - nframes_t first_mtc_time; - static const int32_t accumulator_size = 128; double accumulator[accumulator_size]; int32_t accumulator_index; diff --git a/libs/ardour/mtc_slave.cc b/libs/ardour/mtc_slave.cc index d0af865f5b..a0570f42bc 100644 --- a/libs/ardour/mtc_slave.cc +++ b/libs/ardour/mtc_slave.cc @@ -72,14 +72,11 @@ MTC_Slave::rebind (MIDI::Port& p) void MTC_Slave::update_mtc_qtr (Parser& /*p*/) { - cycles_t cnow = get_cycles (); nframes64_t now = session.engine().frame_time(); nframes_t qtr; - static cycles_t last_qtr = 0; qtr = (long) (session.frames_per_timecode_frame() / 4); mtc_frame += qtr; - last_qtr = cnow; current.guard1++; current.position = mtc_frame; @@ -144,6 +141,7 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full) current.guard1++; current.position = mtc_frame; current.timestamp = 0; + current.speed = 0; current.guard2++; session.request_locate (mtc_frame, false); @@ -154,6 +152,8 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full) } else { + double speed; + /* 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 @@ -163,14 +163,39 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full) mtc_frame += (long) (1.75 * session.frames_per_timecode_frame()) + session.worst_output_latency(); - if (first_mtc_frame == 0) { - first_mtc_frame = mtc_frame; - first_mtc_time = now; + if (current.timestamp != 0) { + + 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)); + + accumulator[accumulator_index++] = speed; + + if (accumulator_index >= accumulator_size) { + have_first_accumulated_speed = true; + accumulator_index = 0; + } + + if (have_first_accumulated_speed) { + double total = 0; + + for (int32_t i = 0; i < accumulator_size; ++i) { + total += accumulator[i]; + } + + speed = total / accumulator_size; + DEBUG_TRACE (DEBUG::MTC, string_compose ("speed smoothed to %1\n", speed)); + } + + } else { + + speed = 0; } current.guard1++; current.position = mtc_frame; current.timestamp = now; + current.speed = speed; current.guard2++; } @@ -194,37 +219,40 @@ MTC_Slave::handle_locate (const MIDI::byte* mmc_tc) void MTC_Slave::update_mtc_status (MIDI::Parser::MTC_Status status) { + /* XXX !!! thread safety ... called from MIDI I/O context + and process() context (via ::speed_and_position()) + */ switch (status) { case MTC_Stopped: - mtc_speed = 0.0f; mtc_frame = 0; current.guard1++; current.position = mtc_frame; current.timestamp = 0; + current.speed = 0; current.guard2++; break; case MTC_Forward: - mtc_speed = 0.0f; mtc_frame = 0; current.guard1++; current.position = mtc_frame; current.timestamp = 0; + current.speed = 0; current.guard2++; break; case MTC_Backward: - mtc_speed = 0.0f; mtc_frame = 0; current.guard1++; current.position = mtc_frame; current.timestamp = 0; + current.speed = 0; current.guard2++; break; @@ -265,13 +293,11 @@ MTC_Slave::speed_and_position (double& speed, nframes64_t& pos) { nframes64_t now = session.engine().frame_time(); SafeTime last; - nframes_t frame_rate; nframes_t elapsed; - double speed_now; read_current (&last); - if (first_mtc_time == 0) { + if (last.timestamp == 0) { speed = 0; pos = last.position; DEBUG_TRACE (DEBUG::MTC, string_compose ("first call to MTC_Slave::speed_and_position, pos = %1\n", last.position)); @@ -281,7 +307,7 @@ MTC_Slave::speed_and_position (double& speed, nframes64_t& pos) /* no timecode for 1/4 second ? conclude that its stopped */ if (last_inbound_frame && now > last_inbound_frame && now - last_inbound_frame > session.frame_rate() / 4) { - mtc_speed = 0; + speed = 0; pos = last.position; session.request_locate (pos, false); session.request_transport_speed (0); @@ -291,37 +317,9 @@ MTC_Slave::speed_and_position (double& speed, nframes64_t& pos) return false; } - frame_rate = session.frame_rate(); - - speed_now = (double) ((last.position - first_mtc_frame) / (double) (now - first_mtc_time)); - - DEBUG_TRACE (DEBUG::MTC, string_compose ("apparent speed = %1 from last %2 now %3 first %4\n", - speed_now, last.position, now, first_mtc_time)); - - - accumulator[accumulator_index++] = speed_now; - - if (accumulator_index >= accumulator_size) { - have_first_accumulated_speed = true; - accumulator_index = 0; - } - - if (have_first_accumulated_speed) { - double total = 0; - - for (int32_t i = 0; i < accumulator_size; ++i) { - total += accumulator[i]; - } - - mtc_speed = total / accumulator_size; - - } else { + DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC::speed_and_position %1 %2\n", last.speed, last.position)); - mtc_speed = speed_now; - - } - - if (mtc_speed == 0.0f) { + if (last.speed == 0.0f) { elapsed = 0; @@ -330,7 +328,7 @@ 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 (mtc_speed * (now - last.timestamp)); + elapsed = (nframes_t) floor (speed * (now - last.timestamp)); } else { elapsed = 0; /* XXX is this right? */ } @@ -339,8 +337,10 @@ MTC_Slave::speed_and_position (double& speed, nframes64_t& pos) /* now add the most recent timecode value plus the estimated elapsed interval */ pos = elapsed + last.position; + speed = last.speed; + + DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC::speed_and_position FINAL %1 %2\n", last.speed, pos)); - speed = mtc_speed; return true; } @@ -364,11 +364,8 @@ MTC_Slave::reset () current.guard1++; current.position = 0; current.timestamp = 0; + current.speed = 0; current.guard2++; - first_mtc_frame = 0; - first_mtc_time = 0; - accumulator_index = 0; have_first_accumulated_speed = false; - mtc_speed = 0; } diff --git a/libs/ardour/session_midi.cc b/libs/ardour/session_midi.cc index 6ff058f3a6..3442ac09a1 100644 --- a/libs/ardour/session_midi.cc +++ b/libs/ardour/session_midi.cc @@ -36,6 +36,7 @@ #include "pbd/pthread_utils.h" #include "ardour/configuration.h" +#include "ardour/debug.h" #include "ardour/audioengine.h" #include "ardour/session.h" #include "ardour/audio_track.h" @@ -833,8 +834,8 @@ Session::send_midi_time_code_for_cycle(nframes_t nframes) /* Duration of one quarter frame */ nframes_t quarter_frame_duration = ((long) _frames_per_timecode_frame) >> 2; - // cerr << "(MTC) TR: " << _transport_frame << " - SF: " << outbound_mtc_timecode_frame - // << " - NQ: " << next_quarter_frame_to_send << " - FD" << quarter_frame_duration << endl; + DEBUG_TRACE (DEBUG::MTC, string_compose ("TF %1 SF %2 NQ %3 FD %\4n", _transport_frame, outbound_mtc_timecode_frame, + next_quarter_frame_to_send, quarter_frame_duration)); // FIXME: this should always be true //assert((outbound_mtc_timecode_frame + (next_quarter_frame_to_send * quarter_frame_duration)) @@ -845,7 +846,7 @@ Session::send_midi_time_code_for_cycle(nframes_t nframes) while (_transport_frame + nframes > (outbound_mtc_timecode_frame + (next_quarter_frame_to_send * quarter_frame_duration))) { - // cerr << "(MTC) Next frame to send: " << next_quarter_frame_to_send << endl; + DEBUG_TRACE (DEBUG::MTC, string_compose ("next frame to send: %1\n", next_quarter_frame_to_send)); switch (next_quarter_frame_to_send) { case 0: @@ -890,13 +891,10 @@ Session::send_midi_time_code_for_cycle(nframes_t nframes) return -1; } - /*cerr << "(MTC) Timecode: " << transmitting_timecode_time.hours - << ":" << transmitting_timecode_time.minutes - << ":" << transmitting_timecode_time.seconds - << ":" << transmitting_timecode_time.frames - << ", qfm = " << next_quarter_frame_to_send - << ", stamp = " << out_stamp - << ", delta = " << _transport_frame + out_stamp - last_time << endl;*/ + DEBUG_STR_SET(foo,"sending "); + DEBUG_STR(foo) << transmitting_timecode_time; + DEBUG_TRACE (DEBUG::MTC, string_compose ("%1 qfm = %2, stamp = %3\n", DEBUG_STR(foo).str(), next_quarter_frame_to_send, + out_stamp)); // Increment quarter frame counter next_quarter_frame_to_send++; |