2 Copyright (C) 2012 Paul Davis
3 Witten by 2012 Robin Gareus <robin@gareus.org>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include <sys/types.h>
25 #include "pbd/error.h"
26 #include "pbd/failed_constructor.h"
27 #include "pbd/pthread_utils.h"
29 #include "ardour/debug.h"
30 #include "ardour/profile.h"
31 #include "ardour/transport_master.h"
32 #include "ardour/session.h"
33 #include "ardour/audioengine.h"
34 #include "ardour/audio_port.h"
39 using namespace ARDOUR;
42 using namespace Timecode;
44 #define ENGINE AudioEngine::instance()
45 #define FLYWHEEL_TIMEOUT ( 1 * ENGINE->sample_rate() )
47 /* XXX USE Config->get_ltc_input */
49 LTC_TransportMaster::LTC_TransportMaster (std::string const & name)
50 : TimecodeTransportMaster (name, LTC)
51 , did_reset_tc_format (false)
53 , samples_per_ltc_frame (0)
54 , fps_detected (false)
57 , ltc_detect_fps_cnt (0)
58 , ltc_detect_fps_max (0)
59 , sync_lock_broken (false)
61 if ((_port = AudioEngine::instance()->register_input_port (DataType::AUDIO, string_compose ("%1 in", _name))) == 0) {
62 throw failed_constructor();
65 DEBUG_TRACE (DEBUG::Slave, string_compose ("LTC registered %1\n", _port->name()));
67 memset(&prev_sample, 0, sizeof(LTCFrameExt));
71 AudioEngine::instance()->Xrun.connect_same_thread (port_connections, boost::bind (<C_TransportMaster::resync_xrun, this));
72 AudioEngine::instance()->GraphReordered.connect_same_thread (port_connections, boost::bind (<C_TransportMaster::resync_latency, this));
76 LTC_TransportMaster::init ()
82 LTC_TransportMaster::set_session (Session *s)
84 config_connection.disconnect ();
89 samples_per_ltc_frame = _session->samples_per_timecode_frame();
90 timecode.rate = _session->timecode_frames_per_second();
91 timecode.drop = _session->timecode_drop_frames();
92 printed_timecode_warning = false;
93 ltc_timecode = _session->config.get_timecode_format();
94 a3e_timecode = _session->config.get_timecode_format();
96 if (Config->get_use_session_timecode_format() && _session) {
97 samples_per_timecode_frame = _session->samples_per_timecode_frame();
101 ltc_decoder_free (decoder);
104 decoder = ltc_decoder_create((int) samples_per_ltc_frame, 128 /*queue size*/);
106 parse_timecode_offset();
109 _session->config.ParameterChanged.connect_same_thread (config_connection, boost::bind (<C_TransportMaster::parameter_changed, this, _1));
113 LTC_TransportMaster::~LTC_TransportMaster()
115 port_connections.drop_connections();
116 config_connection.disconnect();
118 if (did_reset_tc_format) {
119 _session->config.set_timecode_format (saved_tc_format);
122 ltc_decoder_free(decoder);
126 LTC_TransportMaster::parse_timecode_offset() {
127 Timecode::Time offset_tc;
128 Timecode::parse_timecode_format(_session->config.get_slave_timecode_offset(), offset_tc);
129 offset_tc.rate = _session->timecode_frames_per_second();
130 offset_tc.drop = _session->timecode_drop_frames();
131 _session->timecode_to_sample(offset_tc, timecode_offset, false, false);
132 timecode_negative_offset = offset_tc.negative;
136 LTC_TransportMaster::parameter_changed (std::string const & p)
138 if (p == "slave-timecode-offset"
139 || p == "timecode-format"
141 parse_timecode_offset();
146 LTC_TransportMaster::resolution () const
148 return (samplecnt_t) (ENGINE->sample_rate() / 1000);
152 LTC_TransportMaster::locked () const
154 return (delayedlocked < 5);
158 LTC_TransportMaster::ok() const
164 LTC_TransportMaster::resync_xrun()
166 DEBUG_TRACE (DEBUG::LTC, "LTC resync_xrun()\n");
167 sync_lock_broken = false;
171 LTC_TransportMaster::resync_latency()
173 DEBUG_TRACE (DEBUG::LTC, "LTC resync_latency()\n");
174 sync_lock_broken = false;
177 _port->get_connected_latency_range (ltc_slave_latency, false);
182 LTC_TransportMaster::reset (bool with_ts)
184 DEBUG_TRACE (DEBUG::LTC, "LTC reset()\n");
186 current.update (current.position, 0, current.speed);
189 transport_direction = 0;
190 sync_lock_broken = false;
195 LTC_TransportMaster::parse_ltc (const ARDOUR::pframes_t nframes, const Sample* const in, const ARDOUR::samplecnt_t posinfo)
198 unsigned char sound[8192];
200 if (nframes > 8192) {
201 /* TODO warn once or wrap, loop conversion below
202 * does jack/A3 support > 8192 spp anyway?
207 for (i = 0; i < nframes; i++) {
208 const int snd=(int) rint ((127.0*in[i])+128.0);
209 sound[i] = (unsigned char) (snd&0xff);
212 ltc_decoder_write (decoder, sound, nframes, posinfo);
218 LTC_TransportMaster::equal_ltc_sample_time(LTCFrame *a, LTCFrame *b) {
219 if (a->frame_units != b->frame_units ||
220 a->frame_tens != b->frame_tens ||
221 a->dfbit != b->dfbit ||
222 a->secs_units != b->secs_units ||
223 a->secs_tens != b->secs_tens ||
224 a->mins_units != b->mins_units ||
225 a->mins_tens != b->mins_tens ||
226 a->hours_units != b->hours_units ||
227 a->hours_tens != b->hours_tens) {
234 LTC_TransportMaster::detect_discontinuity(LTCFrameExt *sample, int fps, bool fuzzy) {
235 bool discontinuity_detected = false;
238 ( sample->reverse && prev_sample.ltc.frame_units == 0)
239 ||(!sample->reverse && sample->ltc.frame_units == 0)
241 memcpy(&prev_sample, sample, sizeof(LTCFrameExt));
245 if (sample->reverse) {
246 ltc_frame_decrement(&prev_sample.ltc, fps, LTC_TV_525_60, 0);
248 ltc_frame_increment(&prev_sample.ltc, fps, LTC_TV_525_60, 0);
250 if (!equal_ltc_sample_time(&prev_sample.ltc, &sample->ltc)) {
251 discontinuity_detected = true;
254 memcpy(&prev_sample, sample, sizeof(LTCFrameExt));
255 return discontinuity_detected;
259 LTC_TransportMaster::detect_ltc_fps(int frameno, bool df)
261 bool fps_changed = false;
262 double detected_fps = 0;
263 if (frameno > ltc_detect_fps_max)
265 ltc_detect_fps_max = frameno;
267 ltc_detect_fps_cnt++;
269 if (ltc_detect_fps_cnt > 40) {
270 if (ltc_detect_fps_cnt > ltc_detect_fps_max) {
271 detected_fps = ltc_detect_fps_max + 1;
273 /* LTC df -> indicates fractional framerate */
275 detected_fps = detected_fps * 999.0 / 1000.0;
277 detected_fps = detected_fps * 1000.0 / 1001.0;
281 if (timecode.rate != detected_fps || timecode.drop != df) {
282 DEBUG_TRACE (DEBUG::LTC, string_compose ("LTC detected FPS: %1%2\n", detected_fps, df?"df":"ndf"));
284 detected_fps = 0; /* no cange */
287 ltc_detect_fps_cnt = ltc_detect_fps_max = 0;
291 if (detected_fps != 0 && (detected_fps != timecode.rate || df != timecode.drop)) {
292 timecode.rate = detected_fps;
294 samples_per_ltc_frame = double(_session->sample_rate()) / timecode.rate;
295 DEBUG_TRACE (DEBUG::LTC, string_compose ("LTC reset to FPS: %1%2 ; audio-samples per LTC: %3\n",
296 detected_fps, df?"df":"ndf", samples_per_ltc_frame));
300 /* poll and check session TC */
301 TimecodeFormat tc_format = apparent_timecode_format();
302 TimecodeFormat cur_timecode = _session->config.get_timecode_format();
304 if (Config->get_timecode_sync_frame_rate()) {
305 /* enforce time-code */
306 if (!did_reset_tc_format) {
307 saved_tc_format = cur_timecode;
308 did_reset_tc_format = true;
310 if (cur_timecode != tc_format) {
311 if (ceil(Timecode::timecode_to_frames_per_second(cur_timecode)) != ceil(Timecode::timecode_to_frames_per_second(tc_format))) {
312 warning << string_compose(_("Session framerate adjusted from %1 to LTC's %2."),
313 Timecode::timecode_format_name(cur_timecode),
314 Timecode::timecode_format_name(tc_format))
317 _session->config.set_timecode_format (tc_format);
320 /* only warn about TC mismatch */
321 if (ltc_timecode != tc_format) printed_timecode_warning = false;
322 if (a3e_timecode != cur_timecode) printed_timecode_warning = false;
324 if (cur_timecode != tc_format && ! printed_timecode_warning) {
325 if (ceil(Timecode::timecode_to_frames_per_second(cur_timecode)) != ceil(Timecode::timecode_to_frames_per_second(tc_format))) {
326 warning << string_compose(_("Session and LTC framerate mismatch: LTC:%1 Session:%2."),
327 Timecode::timecode_format_name(tc_format),
328 Timecode::timecode_format_name(cur_timecode))
331 printed_timecode_warning = true;
334 ltc_timecode = tc_format;
335 a3e_timecode = cur_timecode;
337 if (Config->get_use_session_timecode_format() && _session) {
338 samples_per_timecode_frame = _session->samples_per_timecode_frame();
340 samples_per_timecode_frame = ENGINE->sample_rate() / Timecode::timecode_to_frames_per_second (ltc_timecode);
347 LTC_TransportMaster::process_ltc(samplepos_t const now)
350 LTC_TV_STANDARD tv_standard = LTC_TV_625_50;
352 while (ltc_decoder_read (decoder, &sample)) {
356 ltc_frame_to_time (&stime, &sample.ltc, 0);
357 timecode.negative = false;
358 timecode.subframes = 0;
360 /* set timecode.rate and timecode.drop: */
362 const bool ltc_is_stationary = equal_ltc_sample_time (&prev_sample.ltc, &sample.ltc);
364 if (detect_discontinuity (&sample, ceil(timecode.rate), !fps_detected)) {
367 ltc_detect_fps_cnt = ltc_detect_fps_max = 0;
370 fps_detected = false;
373 if (!ltc_is_stationary && detect_ltc_fps (stime.frame, (sample.ltc.dfbit)? true : false)) {
379 if (DEBUG_ENABLED (DEBUG::LTC)) {
380 /* use fprintf for simpler correct formatting of times
382 fprintf (stderr, "LTC@%ld %02d:%02d:%02d%c%02d | %8lld %8lld%s\n",
387 (sample.ltc.dfbit) ? '.' : ':',
391 sample.reverse ? " R" : " "
396 /* when a full LTC sample is decoded, the timecode the LTC sample
397 * is referring has just passed.
398 * So we send the _next_ timecode which
399 * is expected to start at the end of the current sample
401 int fps_i = ceil(timecode.rate);
406 tv_standard = LTC_TV_525_60;
408 tv_standard = LTC_TV_1125_60;
412 tv_standard = LTC_TV_625_50;
415 tv_standard = LTC_TV_FILM_24; /* == LTC_TV_1125_60 == no offset, 24,30fps BGF */
419 if (!sample.reverse) {
420 ltc_frame_increment(&sample.ltc, fps_i, tv_standard, 0);
421 ltc_frame_to_time(&stime, &sample.ltc, 0);
422 transport_direction = 1;
423 sample.off_start -= ltc_frame_alignment(samples_per_timecode_frame, tv_standard);
424 sample.off_end -= ltc_frame_alignment(samples_per_timecode_frame, tv_standard);
426 ltc_frame_decrement(&sample.ltc, fps_i, tv_standard, 0);
427 int off = sample.off_end - sample.off_start;
428 sample.off_start += off - ltc_frame_alignment(samples_per_timecode_frame, tv_standard);
429 sample.off_end += off - ltc_frame_alignment(samples_per_timecode_frame, tv_standard);
430 transport_direction = -1;
433 timecode.hours = stime.hours;
434 timecode.minutes = stime.mins;
435 timecode.seconds = stime.secs;
436 timecode.frames = stime.frame;
438 samplepos_t ltc_sample; // audio-sample corresponding to position of LTC frame
440 if (_session && Config->get_use_session_timecode_format()) {
441 Timecode::timecode_to_sample (timecode, ltc_sample, true, false, (double)ENGINE->sample_rate(), _session->config.get_subframes_per_frame(), timecode_negative_offset, timecode_offset);
443 Timecode::timecode_to_sample (timecode, ltc_sample, true, false, (double)ENGINE->sample_rate(), 100, timecode_negative_offset, timecode_offset);
446 ltc_sample += ltc_slave_latency.max;
448 /* This LTC frame spans sample time between sample.off_start .. sample.off_end
450 * NOTE: these sample times are NOT the ones that LTC is representing. They are
451 * derived our own audioengine's monotonic audio clock.
453 * So we expect the next frame to span sample.off_end+1 and ... <don't care for now>.
454 * That isn't the time we will necessarily receive the LTC frame, but the decoder
455 * should tell us that its span begins there.
459 samplepos_t cur_timestamp = sample.off_end + 1;
460 double ltc_speed = current.speed;
462 DEBUG_TRACE (DEBUG::LTC, string_compose ("LTC S: %1 LS: %2 N: %3 L: %4\n", ltc_sample, current.position, cur_timestamp, current.timestamp));
464 if (cur_timestamp <= current.timestamp || current.timestamp == 0) {
465 DEBUG_TRACE (DEBUG::LTC, string_compose ("LTC speed: UNCHANGED: %1\n", current.speed));
467 ltc_speed = double (ltc_sample - current.position) / double (cur_timestamp - current.timestamp);
469 /* provide a .1% deadzone to lock the speed */
470 if (fabs (ltc_speed - 1.0) <= 0.001) {
474 if (fabs (ltc_speed) > 10.0) {
478 DEBUG_TRACE (DEBUG::LTC, string_compose ("LTC speed: %1\n", ltc_speed));
481 current.update (ltc_sample, cur_timestamp, ltc_speed);
483 } /* end foreach decoded LTC sample */
487 LTC_TransportMaster::pre_process (ARDOUR::pframes_t nframes, samplepos_t now, boost::optional<samplepos_t> session_pos)
489 Sample* in = (Sample*) AudioEngine::instance()->port_engine().get_buffer (_port->port_handle(), nframes);
490 sampleoffset_t skip = now - (monotonic_cnt + nframes);
493 DEBUG_TRACE (DEBUG::LTC, string_compose ("pre-process - TID:%1 | latency: %2 | skip %3 | session ? %4| last %5 | dir %6 | sp %7\n",
494 pthread_name(), ltc_slave_latency.max, skip, (_session ? 'y' : 'n'), current.timestamp, transport_direction, current.speed));
496 if (current.timestamp == 0) {
497 if (delayedlocked < 10) {
501 } else if (current.speed != 0) {
505 DEBUG_TRACE (DEBUG::LTC, string_compose ("pre-process with audio clock time: %1\n", now));
507 /* if the audioengine failed to take the process lock, it won't
508 call this method, and time will appear to skip. Reset the
509 LTC decoder's state by giving it some silence.
513 DEBUG_TRACE (DEBUG::LTC, string_compose("engine skipped %1 samples. Feeding silence to LTC parser.\n", skip));
514 if (skip >= 8192) skip = 8192;
515 unsigned char sound[8192];
516 memset (sound, 0x80, sizeof(char) * skip);
517 ltc_decoder_write (decoder, sound, nframes, now);
518 } else if (skip != 0) {
519 /* this should never happen. it may if monotonic_cnt, now overflow on 64bit */
520 DEBUG_TRACE (DEBUG::LTC, string_compose("engine skipped %1 samples\n", skip));
524 /* Now feed the incoming LTC signal into the decoder */
526 parse_ltc (nframes, in, now);
528 /* and pull out actual LTC frame data */
532 if (current.timestamp == 0) {
533 DEBUG_TRACE (DEBUG::LTC, "last timestamp == 0\n");
535 } else if (current.speed != 0) {
536 DEBUG_TRACE (DEBUG::LTC, string_compose ("speed non-zero (%1)\n", current.speed));
537 if (delayedlocked > 1) {
539 } else if (_current_delta == 0) {
544 if (abs (now - current.timestamp) > FLYWHEEL_TIMEOUT) {
545 DEBUG_TRACE (DEBUG::LTC, "flywheel timeout\n");
547 /* don't change position from last known */
552 if (!sync_lock_broken && current.speed != 0 && delayedlocked == 0 && fabs(current.speed) != 1.0) {
553 sync_lock_broken = true;
554 DEBUG_TRACE (DEBUG::LTC, string_compose ("LTC speed not locked based on %1\n", current.speed));
558 const samplepos_t current_pos = current.position + ((now - current.timestamp) * current.speed);
559 _current_delta = current_pos - *session_pos;
565 Timecode::TimecodeFormat
566 LTC_TransportMaster::apparent_timecode_format () const
568 if (timecode.rate == 24 && !timecode.drop)
570 else if (timecode.rate == 25 && !timecode.drop)
572 else if (rint(timecode.rate * 100) == 2997 && !timecode.drop)
573 return (fr2997() ? timecode_2997000 : timecode_2997);
574 else if (rint(timecode.rate * 100) == 2997 && timecode.drop)
575 return (fr2997() ? timecode_2997000drop : timecode_2997drop);
576 else if (timecode.rate == 30 && timecode.drop)
577 return timecode_2997drop; // timecode_30drop; // LTC counting to 30 samples w/DF *means* 29.97 df
578 else if (timecode.rate == 30 && !timecode.drop)
581 /* XXX - unknown timecode format */
582 return _session->config.get_timecode_format();
586 LTC_TransportMaster::position_string() const
588 if (!_collect || current.timestamp == 0) {
589 return " --:--:--:--";
591 return Timecode::timecode_format_time(timecode);
595 LTC_TransportMaster::delta_string() const
599 if (!_collect || current.timestamp == 0) {
600 snprintf (delta, sizeof(delta), "\u2012\u2012\u2012\u2012");
601 } else if ((monotonic_cnt - current.timestamp) > 2 * samples_per_ltc_frame) {
602 snprintf (delta, sizeof(delta), "%s", _("flywheel"));
604 snprintf (delta, sizeof(delta), "\u0394<span foreground=\"%s\" face=\"monospace\" >%s%s%lld</span>sm",
605 sync_lock_broken ? "red" : "green",
606 LEADINGZERO(::llabs(_current_delta)), PLUSMINUS(-_current_delta), ::llabs(_current_delta));