ardour
slave.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002 Paul Davis
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18 */
19 
20 #ifndef __ardour_slave_h__
21 #define __ardour_slave_h__
22 
23 #include <vector>
24 
25 #include <glibmm/threads.h>
26 
27 #include <ltc.h>
28 
29 #include "pbd/signals.h"
30 
31 #include "timecode/time.h"
32 
34 #include "ardour/types.h"
35 #include "midi++/parser.h"
36 #include "midi++/types.h"
37 
38 
39 /* used for approximate_current_delta(): */
40 #define PLUSMINUS(A) ( ((A)<0) ? "-" : (((A)>0) ? "+" : "\u00B1") )
41 #define LEADINGZERO(A) ( (A)<10 ? " " : (A)<100 ? " " : (A)<1000 ? " " : "" )
42 
43 namespace ARDOUR {
44 
45 class TempoMap;
46 class Session;
47 class AudioEngine;
48 class MidiPort;
49 
63  public:
64  Slave() { }
65  virtual ~Slave() {}
66 
119  virtual bool speed_and_position (double& speed, framepos_t& position) = 0;
120 
127  virtual bool locked() const = 0;
128 
135  virtual bool ok() const = 0;
136 
143  virtual bool starting() const { return false; }
144 
149  virtual framecnt_t resolution() const = 0;
150 
155  virtual bool requires_seekahead () const = 0;
156 
162  virtual framecnt_t seekahead_distance() const { return 0; }
163 
168  virtual bool is_always_synced() const { return false; }
169 
173  virtual bool give_slave_full_control_over_transport_speed() const { return false; }
174 
178  virtual std::string approximate_current_delta() const { return ""; }
179 
180 };
181 
184  public:
185  virtual ~ISlaveSessionProxy() {}
186  virtual TempoMap& tempo_map() const { return *((TempoMap *) 0); }
187  virtual framecnt_t frame_rate() const { return 0; }
188  virtual pframes_t frames_per_cycle() const { return 0; }
189  virtual framepos_t audible_frame () const { return 0; }
190  virtual framepos_t transport_frame () const { return 0; }
191  virtual pframes_t frames_since_cycle_start () const { return 0; }
192  virtual framepos_t sample_time_at_cycle_start() const { return 0; }
193  virtual framepos_t frame_time () const { return 0; }
194 
195  virtual void request_locate (framepos_t /*frame*/, bool with_roll = false) {
196  (void) with_roll;
197  }
198  virtual void request_transport_speed (double /*speed*/) {}
199 };
200 
201 
205 
206  public:
207  SlaveSessionProxy(Session &s) : session(s) {}
208 
209  TempoMap& tempo_map() const;
210  framecnt_t frame_rate() const;
211  pframes_t frames_per_cycle() const;
212  framepos_t audible_frame () const;
213  framepos_t transport_frame () const;
214  pframes_t frames_since_cycle_start () const;
215  framepos_t sample_time_at_cycle_start() const;
216  framepos_t frame_time () const;
217 
218  void request_locate (framepos_t frame, bool with_roll = false);
219  void request_transport_speed (double speed);
220 };
221 
223  volatile int guard1;
226  double speed;
227  volatile int guard2;
228 
230  guard1 = 0;
231  position = 0;
232  timestamp = 0;
233  speed = 0;
234  guard2 = 0;
235  }
236 };
237 
239  public:
241 
242  virtual Timecode::TimecodeFormat apparent_timecode_format() const = 0;
243 
244  /* this is intended to be used by a UI and polled from a timeout. it should
245  return a string describing the current position of the TC source. it
246  should NOT do any computation, but should use a cached value
247  of the TC source position.
248  */
249  virtual std::string approximate_current_position() const = 0;
250 
253 };
254 
256  public:
258  ~MTC_Slave ();
259 
260  void rebind (MidiPort&);
261  bool speed_and_position (double&, framepos_t&);
262 
263  bool locked() const;
264  bool ok() const;
265  void handle_locate (const MIDI::byte*);
266 
267  framecnt_t resolution () const;
268  bool requires_seekahead () const { return false; }
269  framecnt_t seekahead_distance() const;
270  bool give_slave_full_control_over_transport_speed() const;
271 
272  Timecode::TimecodeFormat apparent_timecode_format() const;
273  std::string approximate_current_position() const;
274  std::string approximate_current_delta() const;
275 
276  private:
282 
283  static const int frame_tolerance;
284 
286  framepos_t mtc_frame; /* current time */
288  framepos_t last_inbound_frame; /* when we got it; audio clocked */
289  MIDI::byte last_mtc_fps_byte;
294  Timecode::TimecodeFormat saved_tc_format;
295  Glib::Threads::Mutex reset_lock;
296  uint32_t reset_pending;
301 
304  Timecode::TimecodeFormat mtc_timecode;
305  Timecode::TimecodeFormat a3e_timecode;
306  Timecode::Time timecode;
309 
310  /* DLL - chase MTC */
311  double t0;
312  double t1;
313  double e2;
314  double b, c, omega;
315 
316  /* DLL - sync engine */
318  double te0;
319  double te1;
320  double ee2;
321  double be, ce, oe;
322 
323  void reset (bool with_pos);
324  void queue_reset (bool with_pos);
325  void maybe_reset ();
326 
327  void update_mtc_qtr (MIDI::Parser&, int, framepos_t);
328  void update_mtc_time (const MIDI::byte *, bool, framepos_t);
329  void update_mtc_status (MIDI::MTC_Status);
330  void read_current (SafeTime *) const;
331  void reset_window (framepos_t);
332  bool outside_window (framepos_t) const;
333  void init_mtc_dll(framepos_t, double);
334  void init_engine_dll (framepos_t, framepos_t);
335  void parse_timecode_offset();
336  void parameter_changed(std::string const & p);
337 };
338 
340 public:
341  LTC_Slave (Session&);
342  ~LTC_Slave ();
343 
344  bool speed_and_position (double&, framepos_t&);
345 
346  bool locked() const;
347  bool ok() const;
348 
349  framecnt_t resolution () const;
350  bool requires_seekahead () const { return false; }
351  framecnt_t seekahead_distance () const { return 0; }
352  bool give_slave_full_control_over_transport_speed() const { return true; }
353 
354  Timecode::TimecodeFormat apparent_timecode_format() const;
355  std::string approximate_current_position() const;
356  std::string approximate_current_delta() const;
357 
358  private:
359  void parse_ltc(const pframes_t, const Sample* const, const framecnt_t);
360  void process_ltc(framepos_t const);
361  void init_engine_dll (framepos_t, int32_t);
362  bool detect_discontinuity(LTCFrameExt *, int, bool);
363  bool detect_ltc_fps(int, bool);
364  bool equal_ltc_frame_time(LTCFrame *a, LTCFrame *b);
365  void reset();
366  void resync_xrun();
367  void resync_latency();
368  void parse_timecode_offset();
369  void parameter_changed(std::string const & p);
370 
373  Timecode::TimecodeFormat saved_tc_format;
374 
375  LTCDecoder * decoder;
377  Timecode::Time timecode;
378  LTCFrameExt prev_frame;
380 
384  double ltc_speed;
387 
392  Timecode::TimecodeFormat ltc_timecode;
393  Timecode::TimecodeFormat a3e_timecode;
394 
398 
399  /* DLL - chase LTC */
402  double t0;
403  double t1;
404  double e2;
405  double b, c;
406 };
407 
409  public:
410  MIDIClock_Slave (Session&, MidiPort&, int ppqn = 24);
411 
413  MIDIClock_Slave (ISlaveSessionProxy* session_proxy = 0, int ppqn = 24);
414  ~MIDIClock_Slave ();
415 
416  void rebind (MidiPort&);
417  bool speed_and_position (double&, framepos_t&);
418 
419  bool locked() const;
420  bool ok() const;
421  bool starting() const;
422 
423  framecnt_t resolution () const;
424  bool requires_seekahead () const { return false; }
425  bool give_slave_full_control_over_transport_speed() const { return true; }
426 
427  void set_bandwidth (double a_bandwith) { bandwidth = a_bandwith; }
428  std::string approximate_current_delta() const;
429 
430  protected:
433 
435  int ppqn;
436 
439 
442 
446 
450 
451  //the delay locked loop (DLL), see www.kokkinizita.net/papers/usingdll.pdf
452 
454  double t0;
455 
457  double t1;
458 
460  double e;
461 
463  double e2;
464 
466  double bandwidth;
467 
469  double b, c, omega;
470 
472 
473  void reset ();
474  void start (MIDI::Parser& parser, framepos_t timestamp);
475  void contineu (MIDI::Parser& parser, framepos_t timestamp);
476  void stop (MIDI::Parser& parser, framepos_t timestamp);
477  void position (MIDI::Parser& parser, MIDI::byte* message, size_t size);
478  // we can't use continue because it is a C++ keyword
479  void calculate_one_ppqn_in_frames_at(framepos_t time);
480  framepos_t calculate_song_position(uint16_t song_position_in_sixteenth_notes);
481  void calculate_filter_coefficients();
482  void update_midi_clock (MIDI::Parser& parser, framepos_t timestamp);
483  void read_current (SafeTime *) const;
484  bool stop_if_no_more_clock_events(framepos_t& pos, framepos_t now);
485 
487  bool _started;
488 
491  bool _starting;
492 };
493 
495 {
496  public:
498  ~Engine_Slave ();
499 
500  bool speed_and_position (double& speed, framepos_t& pos);
501 
502  bool starting() const { return _starting; }
503  bool locked() const;
504  bool ok() const;
505  framecnt_t resolution () const { return 1; }
506  bool requires_seekahead () const { return false; }
507  bool is_always_synced() const { return true; }
508 
509  private:
511  bool _starting;
512 };
513 
514 } /* namespace */
515 
516 #endif /* __ardour_slave_h__ */
double t1
calculated end of the MTC quater frame
Definition: slave.h:403
bool timecode_negative_offset
Definition: slave.h:252
bool give_slave_full_control_over_transport_speed() const
Definition: slave.h:352
framecnt_t last_ltc_frame
Definition: slave.h:383
double te1
calculated sync time
Definition: slave.h:319
bool printed_timecode_warning
Definition: slave.h:390
ISlaveSessionProxy * session
Definition: slave.h:431
framepos_t mtc_frame
Definition: slave.h:286
void set_bandwidth(double a_bandwith)
Definition: slave.h:427
LTCFrameExt prev_frame
Definition: slave.h:378
virtual void request_transport_speed(double)
Definition: slave.h:198
framepos_t last_timestamp
the time stamp and should-be transport position of the last inbound MIDI clock message ...
Definition: slave.h:444
double ltc_speed
Definition: slave.h:384
double should_be_position
Definition: slave.h:445
int engine_dll_initstate
Definition: slave.h:401
virtual framecnt_t seekahead_distance() const
Definition: slave.h:162
framepos_t position
Definition: slave.h:224
double omega
DLL filter coefficients.
Definition: slave.h:314
framepos_t last_inbound_frame
Definition: slave.h:288
We need this wrapper for testability, it's just too hard to mock up a session class.
Definition: slave.h:183
frameoffset_t current_delta
Definition: slave.h:385
Glib::Threads::Mutex reset_lock
Definition: slave.h:295
Session & session
Definition: slave.h:277
PBD::ScopedConnection config_connection
Definition: slave.h:396
Timecode::TimecodeFormat a3e_timecode
Definition: slave.h:305
uint32_t pframes_t
Definition: types.h:61
virtual framepos_t transport_frame() const
Definition: slave.h:190
virtual framecnt_t frame_rate() const
Definition: slave.h:187
double te0
time at the beginning of the engine process
Definition: slave.h:318
Session & session
Definition: slave.h:371
virtual framepos_t audible_frame() const
Definition: slave.h:189
virtual bool starting() const
Definition: slave.h:143
framepos_t first_mtc_timestamp
Definition: slave.h:292
double e
loop error = real value - expected value
Definition: slave.h:460
PBD::ScopedConnectionList port_connections
Definition: slave.h:432
double t0
time at the beginning of the MTC quater frame
Definition: slave.h:311
bool requires_seekahead() const
Definition: slave.h:506
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > start
Definition: region.cc:63
double one_ppqn_in_frames
the duration of one ppqn in frame time
Definition: slave.h:438
virtual pframes_t frames_since_cycle_start() const
Definition: slave.h:191
uint32_t reset_pending
Definition: slave.h:296
int transport_direction
Definition: slave.h:298
framecnt_t monotonic_cnt
Definition: slave.h:381
LIBARDOUR_API uint64_t TempoMap
Definition: debug.cc:60
framepos_t timecode_offset
Definition: slave.h:251
PBD::ScopedConnectionList port_connections
Definition: slave.h:279
int transport_direction
Definition: slave.h:400
bool can_notify_on_unknown_rate
Definition: slave.h:281
double bandwidth
DLL filter bandwidth.
Definition: slave.h:466
int64_t framecnt_t
Definition: types.h:76
double c
DLL filter coefficients.
Definition: slave.h:405
int ppqn
pulses per quarter note for one MIDI clock frame (default 24)
Definition: slave.h:435
float Sample
Definition: types.h:54
LatencyRange ltc_slave_latency
Definition: slave.h:397
bool did_reset_tc_format
Definition: slave.h:293
double t0
time at the beginning of the MTC quater frame
Definition: slave.h:402
double speed
Definition: slave.h:226
LTCDecoder * decoder
Definition: slave.h:375
PBD::ScopedConnection config_connection
Definition: slave.h:280
Definition: amp.h:29
double e2
second order loop error
Definition: slave.h:404
LIBARDOUR_API PBD::PropertyDescriptor< bool > locked
Definition: region.cc:51
virtual framepos_t frame_time() const
Definition: slave.h:193
The Slave interface can be used to sync ARDOURs tempo to an external source like MTC, MIDI Clock, etc.
Definition: slave.h:62
SafeTime current
Definition: slave.h:285
framepos_t timestamp
Definition: slave.h:225
framecnt_t resolution() const
Definition: slave.h:505
bool sync_lock_broken
Definition: slave.h:391
framecnt_t last_timestamp
Definition: slave.h:382
frameoffset_t current_delta
Definition: slave.h:471
int64_t framepos_t
Definition: types.h:66
framepos_t window_end
Definition: slave.h:291
Timecode::TimecodeFormat saved_tc_format
Definition: slave.h:294
int delayedlocked
Definition: slave.h:386
bool requires_seekahead() const
Definition: slave.h:424
int64_t frameoffset_t
Definition: types.h:71
double speedup_due_to_tc_mismatch
Definition: slave.h:302
virtual bool is_always_synced() const
Definition: slave.h:168
bool give_slave_full_control_over_transport_speed() const
Definition: slave.h:425
static const int frame_tolerance
Definition: slave.h:283
Timecode::TimecodeFormat a3e_timecode
Definition: slave.h:393
#define LIBARDOUR_API
int ltc_detect_fps_cnt
Definition: slave.h:388
SlaveSessionProxy(Session &s)
Definition: slave.h:207
bool requires_seekahead() const
Definition: slave.h:350
double t0
time at the beginning of the MIDI clock frame
Definition: slave.h:454
virtual bool give_slave_full_control_over_transport_speed() const
Definition: slave.h:173
Timecode::Time timecode
Definition: slave.h:377
virtual ~ISlaveSessionProxy()
Definition: slave.h:185
Timecode::TimecodeFormat ltc_timecode
Definition: slave.h:392
bool did_reset_tc_format
Definition: slave.h:372
bool reset_position
Definition: slave.h:297
int ltc_detect_fps_max
Definition: slave.h:389
double quarter_frame_duration
Definition: slave.h:303
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > position
Definition: region.cc:65
bool requires_seekahead() const
Definition: slave.h:268
virtual ~Slave()
Definition: slave.h:65
frameoffset_t current_delta
Definition: slave.h:308
bool fps_detected
Definition: slave.h:379
bool is_always_synced() const
Definition: slave.h:507
MIDI::byte last_mtc_fps_byte
Definition: slave.h:289
virtual TempoMap & tempo_map() const
Definition: slave.h:186
double t1
calculated end of the MTC quater frame
Definition: slave.h:312
double ee2
second order loop error
Definition: slave.h:320
int engine_dll_initstate
Definition: slave.h:317
PBD::ScopedConnectionList port_connections
Definition: slave.h:395
bool _started
whether transport should be rolling
Definition: slave.h:487
volatile int guard1
Definition: slave.h:223
bool printed_timecode_warning
Definition: slave.h:307
double mtc_frame_dll
Definition: slave.h:287
The Session Proxy for use in real Ardour.
Definition: slave.h:203
framepos_t first_timestamp
the timestamp of the first MIDI clock message
Definition: slave.h:441
LIBARDOUR_API uint64_t AudioEngine
Definition: session.h:982
virtual void request_locate(framepos_t, bool with_roll=false)
Definition: slave.h:195
virtual framepos_t sample_time_at_cycle_start() const
Definition: slave.h:192
double frames_per_ltc_frame
Definition: slave.h:376
AudioEngine & engine
Definition: slave.h:510
Timecode::TimecodeFormat mtc_timecode
Definition: slave.h:304
virtual pframes_t frames_per_cycle() const
Definition: slave.h:188
double e2
second order loop error
Definition: slave.h:463
double oe
DLL filter coefficients.
Definition: slave.h:321
Timecode::TimecodeFormat saved_tc_format
Definition: slave.h:373
virtual std::string approximate_current_delta() const
Definition: slave.h:178
framecnt_t seekahead_distance() const
Definition: slave.h:351
bool starting() const
Definition: slave.h:502
Timecode::Time timecode
Definition: slave.h:306
double t1
calculated end of the MIDI clock frame
Definition: slave.h:457
double e2
second order loop error
Definition: slave.h:313
framepos_t window_begin
Definition: slave.h:290
volatile int guard2
Definition: slave.h:227
MidiPort * port
Definition: slave.h:278