2
Copyright (C) 2002 Paul Davis
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.
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.
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.
20
#ifndef __ardour_slave_h__
21
#define __ardour_slave_h__
25
#include <glibmm/threads.h>
27
#include <jack/jack.h>
29
#include "pbd/signals.h"
31
#include "timecode/time.h"
34
#include "ardour/types.h"
35
#include "midi++/parser.h"
36
#include "midi++/types.h"
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 ? " " : "" )
55
* @brief The Slave interface can be used to sync ARDOURs tempo to an external source
56
* like MTC, MIDI Clock, etc.
58
* The name of the interface may be a bit misleading: A subclass of Slave actually
59
* acts as a time master for ARDOUR, that means ARDOUR will try to follow the
60
* speed and transport position of the implementation of Slave.
61
* Therefore it is rather that class, that makes ARDOUR a slave by connecting it
62
* to its external time master.
70
* This is the most important function to implement:
71
* Each process cycle, Session::follow_slave will call this method.
72
* and after the method call they should
74
* Session::follow_slave will then try to follow the given
75
* <em>position</em> using a delay locked loop (DLL),
76
* starting with the first given transport speed.
77
* If the values of speed and position contradict each other,
78
* ARDOUR will always follow the position and disregard the speed.
79
* Although, a correct speed is important so that ARDOUR
80
* can sync to the master time source quickly.
82
* For background information on delay locked loops,
83
* see http://www.kokkinizita.net/papers/usingdll.pdf
85
* The method has the following precondition:
88
* Slave::ok() should return true, otherwise playback will stop
89
* immediately and the method will not be called
92
* when the references speed and position are passed into the Slave
93
* they are uninitialized
97
* After the method call the following postconditions should be met:
100
* The first position value on transport start should be 0,
101
* otherwise ARDOUR will try to locate to the new position
102
* rather than move to it
105
* the references speed and position should be assigned
106
* to the Slaves current requested transport speed
107
* and transport position.
110
* Slave::resolution() should be greater than the maximum distance of
111
* ARDOURs transport position to the slaves requested transport position.
113
* <li>Slave::locked() should return true, otherwise Session::no_roll will be called</li>
114
* <li>Slave::starting() should be false, otherwise the transport will not move until it becomes true</li> *
117
* @param speed - The transport speed requested
118
* @param position - The transport position requested
119
* @return - The return value is currently ignored (see Session::follow_slave)
121
virtual bool speed_and_position (double& speed, framepos_t& position) = 0;
124
* reports to ARDOUR whether the Slave is currently synced to its external
127
* @return - when returning false, the transport will stop rolling
129
virtual bool locked() const = 0;
132
* reports to ARDOUR whether the slave is in a sane state
134
* @return - when returning false, the transport will be stopped and the slave
135
* disconnected from ARDOUR.
137
virtual bool ok() const = 0;
140
* reports to ARDOUR whether the slave is in the process of starting
143
* @return - when returning false, transport will not move until this method returns true
145
virtual bool starting() const { return false; }
148
* @return - the timing resolution of the Slave - If the distance of ARDOURs transport
149
* to the slave becomes greater than the resolution, sound will stop
151
virtual framecnt_t resolution() const = 0;
154
* @return - when returning true, ARDOUR will wait for seekahead_distance() before transport
157
virtual bool requires_seekahead () const = 0;
160
* @return the number of frames that this slave wants to seek ahead. Relevant
161
* only if requires_seekahead() returns true.
164
virtual framecnt_t seekahead_distance() const { return 0; }
167
* @return - when returning true, ARDOUR will use transport speed 1.0 no matter what
170
virtual bool is_always_synced() const { return false; }
173
* @return - whether ARDOUR should use the slave speed without any adjustments
175
virtual bool give_slave_full_control_over_transport_speed() const { return false; }
178
* @return - current time-delta between engine and sync-source
180
virtual std::string approximate_current_delta() const { return ""; }
184
/// We need this wrapper for testability, it's just too hard to mock up a session class
185
class ISlaveSessionProxy {
187
virtual ~ISlaveSessionProxy() {}
188
virtual TempoMap& tempo_map() const { return *((TempoMap *) 0); }
189
virtual framecnt_t frame_rate() const { return 0; }
190
virtual framepos_t audible_frame () const { return 0; }
191
virtual framepos_t transport_frame () const { return 0; }
192
virtual pframes_t frames_since_cycle_start () const { return 0; }
193
virtual framepos_t frame_time () const { return 0; }
195
virtual void request_locate (framepos_t /*frame*/, bool with_roll = false) {
198
virtual void request_transport_speed (double /*speed*/) {}
202
/// The Session Proxy for use in real Ardour
203
class SlaveSessionProxy : public ISlaveSessionProxy {
207
SlaveSessionProxy(Session &s) : session(s) {}
209
TempoMap& tempo_map() const;
210
framecnt_t frame_rate() const;
211
framepos_t audible_frame () const;
212
framepos_t transport_frame () const;
213
pframes_t frames_since_cycle_start () const;
214
framepos_t frame_time () const;
216
void request_locate (framepos_t frame, bool with_roll = false);
217
void request_transport_speed (double speed);
223
framepos_t timestamp;
236
class TimecodeSlave : public Slave {
240
virtual Timecode::TimecodeFormat apparent_timecode_format() const = 0;
242
/* this is intended to be used by a UI and polled from a timeout. it should
243
return a string describing the current position of the TC source. it
244
should NOT do any computation, but should use a cached value
245
of the TC source position.
247
virtual std::string approximate_current_position() const = 0;
249
framepos_t timecode_offset;
250
bool timecode_negative_offset;
253
class MTC_Slave : public TimecodeSlave {
255
MTC_Slave (Session&, MIDI::Port&);
258
void rebind (MIDI::Port&);
259
bool speed_and_position (double&, framepos_t&);
263
void handle_locate (const MIDI::byte*);
265
framecnt_t resolution () const;
266
bool requires_seekahead () const { return false; }
267
framecnt_t seekahead_distance() const;
268
bool give_slave_full_control_over_transport_speed() const;
270
Timecode::TimecodeFormat apparent_timecode_format() const;
271
std::string approximate_current_position() const;
272
std::string approximate_current_delta() const;
277
PBD::ScopedConnectionList port_connections;
278
PBD::ScopedConnection config_connection;
279
bool can_notify_on_unknown_rate;
281
static const int frame_tolerance;
284
framepos_t mtc_frame; /* current time */
285
double mtc_frame_dll;
286
framepos_t last_inbound_frame; /* when we got it; audio clocked */
287
MIDI::byte last_mtc_fps_byte;
288
framepos_t window_begin;
289
framepos_t window_end;
290
framepos_t first_mtc_timestamp;
291
bool did_reset_tc_format;
292
Timecode::TimecodeFormat saved_tc_format;
293
Glib::Threads::Mutex reset_lock;
294
uint32_t reset_pending;
296
int transport_direction;
300
double speedup_due_to_tc_mismatch;
301
double quarter_frame_duration;
302
Timecode::TimecodeFormat mtc_timecode;
303
Timecode::TimecodeFormat a3e_timecode;
304
Timecode::Time timecode;
305
bool printed_timecode_warning;
306
frameoffset_t current_delta;
308
/* DLL - chase MTC */
309
double t0; ///< time at the beginning of the MTC quater frame
310
double t1; ///< calculated end of the MTC quater frame
311
double e2; ///< second order loop error
312
double b, c, omega; ///< DLL filter coefficients
314
/* DLL - sync engine */
315
int engine_dll_initstate;
316
double te0; ///< time at the beginning of the engine process
317
double te1; ///< calculated sync time
318
double ee2; ///< second order loop error
319
double be, ce, oe; ///< DLL filter coefficients
321
void reset (bool with_pos);
322
void queue_reset (bool with_pos);
325
void update_mtc_qtr (MIDI::Parser&, int, framepos_t);
326
void update_mtc_time (const MIDI::byte *, bool, framepos_t);
327
void update_mtc_status (MIDI::MTC_Status);
328
void read_current (SafeTime *) const;
329
void reset_window (framepos_t);
330
bool outside_window (framepos_t) const;
331
void init_mtc_dll(framepos_t, double);
332
void init_engine_dll (framepos_t, framepos_t);
333
void parse_timecode_offset();
334
void parameter_changed(std::string const & p);
337
class LTC_Slave : public TimecodeSlave {
339
LTC_Slave (Session&);
342
bool speed_and_position (double&, framepos_t&);
347
framecnt_t resolution () const;
348
bool requires_seekahead () const { return false; }
349
framecnt_t seekahead_distance () const { return 0; }
350
bool give_slave_full_control_over_transport_speed() const { return true; }
352
Timecode::TimecodeFormat apparent_timecode_format() const;
353
std::string approximate_current_position() const;
354
std::string approximate_current_delta() const;
357
void parse_ltc(const jack_nframes_t, const jack_default_audio_sample_t * const, const framecnt_t);
358
void process_ltc(framepos_t const);
359
void init_engine_dll (framepos_t, int32_t);
360
bool detect_discontinuity(LTCFrameExt *, int, bool);
361
bool detect_ltc_fps(int, bool);
362
bool equal_ltc_frame_time(LTCFrame *a, LTCFrame *b);
365
void resync_latency();
366
void parse_timecode_offset();
367
void parameter_changed(std::string const & p);
370
bool did_reset_tc_format;
371
Timecode::TimecodeFormat saved_tc_format;
373
LTCDecoder * decoder;
374
double frames_per_ltc_frame;
375
Timecode::Time timecode;
376
LTCFrameExt prev_frame;
379
framecnt_t monotonic_cnt;
380
framecnt_t last_timestamp;
381
framecnt_t last_ltc_frame;
383
frameoffset_t current_delta;
386
int ltc_detect_fps_cnt;
387
int ltc_detect_fps_max;
388
bool printed_timecode_warning;
389
Timecode::TimecodeFormat ltc_timecode;
390
Timecode::TimecodeFormat a3e_timecode;
392
PBD::ScopedConnectionList port_connections;
393
PBD::ScopedConnection config_connection;
394
jack_latency_range_t ltc_slave_latency;
396
/* DLL - chase LTC */
397
int transport_direction;
398
int engine_dll_initstate;
399
double t0; ///< time at the beginning of the MTC quater frame
400
double t1; ///< calculated end of the MTC quater frame
401
double e2; ///< second order loop error
402
double b, c; ///< DLL filter coefficients
405
class MIDIClock_Slave : public Slave {
407
MIDIClock_Slave (Session&, MIDI::Port&, int ppqn = 24);
409
/// Constructor for unit tests
410
MIDIClock_Slave (ISlaveSessionProxy* session_proxy = 0, int ppqn = 24);
413
void rebind (MIDI::Port&);
414
bool speed_and_position (double&, framepos_t&);
418
bool starting() const;
420
framecnt_t resolution () const;
421
bool requires_seekahead () const { return false; }
422
bool give_slave_full_control_over_transport_speed() const { return true; }
424
void set_bandwidth (double a_bandwith) { bandwidth = a_bandwith; }
425
std::string approximate_current_delta() const;
428
ISlaveSessionProxy* session;
430
PBD::ScopedConnectionList port_connections;
432
/// pulses per quarter note for one MIDI clock frame (default 24)
435
/// the duration of one ppqn in frame time
436
double one_ppqn_in_frames;
438
/// the timestamp of the first MIDI clock message
439
framepos_t first_timestamp;
441
/// the time stamp and should-be transport position of the last inbound MIDI clock message
442
framepos_t last_timestamp;
443
double should_be_position;
445
/// the number of midi clock messages received (zero-based)
447
long midi_clock_count;
449
//the delay locked loop (DLL), see www.kokkinizita.net/papers/usingdll.pdf
451
/// time at the beginning of the MIDI clock frame
454
/// calculated end of the MIDI clock frame
457
/// loop error = real value - expected value
460
/// second order loop error
463
/// DLL filter bandwidth
466
/// DLL filter coefficients
469
frameoffset_t current_delta;
472
void start (MIDI::Parser& parser, framepos_t timestamp);
473
void contineu (MIDI::Parser& parser, framepos_t timestamp);
474
void stop (MIDI::Parser& parser, framepos_t timestamp);
475
void position (MIDI::Parser& parser, MIDI::byte* message, size_t size);
476
// we can't use continue because it is a C++ keyword
477
void calculate_one_ppqn_in_frames_at(framepos_t time);
478
framepos_t calculate_song_position(uint16_t song_position_in_sixteenth_notes);
479
void calculate_filter_coefficients();
480
void update_midi_clock (MIDI::Parser& parser, framepos_t timestamp);
481
void read_current (SafeTime *) const;
482
bool stop_if_no_more_clock_events(framepos_t& pos, framepos_t now);
484
/// whether transport should be rolling
487
/// is true if the MIDI Start message has just been received until
488
/// the first MIDI Clock Event
492
class JACK_Slave : public Slave
495
JACK_Slave (jack_client_t*);
498
bool speed_and_position (double& speed, framepos_t& pos);
500
bool starting() const { return _starting; }
503
framecnt_t resolution () const { return 1; }
504
bool requires_seekahead () const { return false; }
505
void reset_client (jack_client_t* jack);
506
bool is_always_synced() const { return true; }
516
#endif /* __ardour_slave_h__ */