+
+ calculate_one_ppqn_in_frames_at(should_be_position);
+
+ nframes64_t elapsed_since_start = timestamp - first_timestamp;
+ double error = 0;
+
+ if (_starting || last_timestamp == 0) {
+ midi_clock_count = 0;
+
+ first_timestamp = timestamp;
+ elapsed_since_start = should_be_position;
+
+ // calculate filter coefficients
+ calculate_filter_coefficients();
+
+ // initialize DLL
+ e2 = double(one_ppqn_in_frames) / double(session->frame_rate());
+ t0 = double(elapsed_since_start) / double(session->frame_rate());
+ t1 = t0 + e2;
+
+ // let ardour go after first MIDI Clock Event
+ _starting = false;
+ } else {
+ midi_clock_count++;
+ should_be_position += one_ppqn_in_frames;
+ calculate_filter_coefficients();
+
+ // calculate loop error
+ // we use session->transport_frame() instead of t1 here
+ // because t1 is used to calculate the transport speed,
+ // so the loop will compensate for accumulating rounding errors
+ error = (double(should_be_position) - double(session->audible_frame()));
+ e = error / double(session->frame_rate());
+
+ // update DLL
+ t0 = t1;
+ t1 += b * e + e2;
+ e2 += c * e;
+ }
+
+ #ifdef DEBUG_MIDI_CLOCK
+ cerr
+ << "MIDI Clock #" << midi_clock_count
+ //<< "@" << timestamp
+ << " arrived at: " << elapsed_since_start << " (elapsed time) "
+ << " should-be transport: " << should_be_position
+ << " audible: " << session->audible_frame()
+ << " real transport: " << session->transport_frame()
+ << " error: " << error
+ //<< " engine: " << session->frame_time()
+ << " real delta: " << timestamp - last_timestamp
+ << " should-be delta: " << one_ppqn_in_frames
+ << " t1-t0: " << (t1 -t0) * session->frame_rate()
+ << " t0: " << t0 * session->frame_rate()
+ << " t1: " << t1 * session->frame_rate()
+ << " frame-rate: " << session->frame_rate()
+ << endl;
+
+ cerr << "frames since cycle start: " << session->frames_since_cycle_start() << endl;
+ #endif // DEBUG_MIDI_CLOCK
+
+ last_timestamp = timestamp;
+}
+
+void
+MIDIClock_Slave::start (Parser& /*parser*/, nframes64_t /*timestamp*/)
+{
+ #ifdef DEBUG_MIDI_CLOCK
+ cerr << "MIDIClock_Slave got start message at time " << timestamp << " engine time: " << session->frame_time() << endl;
+ #endif
+
+ if (!_started) {
+ reset();
+
+ _started = true;
+ _starting = true;
+ }
+}
+
+void
+MIDIClock_Slave::reset ()
+{
+
+ should_be_position = 0;
+ last_timestamp = 0;
+
+ _starting = false;
+ _started = false;
+
+ session->request_locate(0, false);