summaryrefslogtreecommitdiff
path: root/libs/ardour/session_ltc.cc
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2012-10-24 18:33:30 +0000
committerRobin Gareus <robin@gareus.org>2012-10-24 18:33:30 +0000
commitacb795980b5cc5bd1d52ccabaab64e4f135e8888 (patch)
treea5352748bd40fc5fc079c4ae15d9a7fc03b33cb4 /libs/ardour/session_ltc.cc
parentead6e3ade91a35425cddf24ddf528c02f2e1aa97 (diff)
mostly cosmetic changes to LTC generator
also enable latency compensation and disable LTC gen from MClk (both of which should have been in prev commit, but commented here) git-svn-id: svn://localhost/ardour2/branches/3.0@13335 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour/session_ltc.cc')
-rw-r--r--libs/ardour/session_ltc.cc87
1 files changed, 54 insertions, 33 deletions
diff --git a/libs/ardour/session_ltc.cc b/libs/ardour/session_ltc.cc
index 317d6af7c1..c10e62659c 100644
--- a/libs/ardour/session_ltc.cc
+++ b/libs/ardour/session_ltc.cc
@@ -22,6 +22,7 @@
#include "ardour/session.h"
#include "ardour/audioengine.h"
#include "ardour/audio_port.h"
+#include "ardour/slave.h"
#include "i18n.h"
@@ -113,13 +114,18 @@ Session::ltc_tx_send_time_code_for_cycle (framepos_t start_frame, framepos_t end
out = (jack_default_audio_sample_t*) jack_port_get_buffer (ltcport->jack_port(), nframes);
if (!out) return 0;
- if (engine().freewheeling()|| !Config->get_send_ltc()
+ SyncSource sync_src = Config->get_sync_source();
+ if (engine().freewheeling()
+ || !Config->get_send_ltc()
/* TODO
- * we can relax this a bit, JACK or sample-synced slaves should be fine.
- * test before allowing it, do the same for MTC generator in
- * libs/ardour/session_midi.cc
- * */
- // || config.get_external_sync() // XXX XXX
+ * decide which time-sources we can generated LTC from.
+ * Internal, JACK or sample-synced slaves should be fine.
+ *
+ *
+ || (config.get_external_sync() && sync_src == LTC)
+ || (config.get_external_sync() && sync_src == MTC)
+ */
+ || (config.get_external_sync() && sync_src == MIDIClock)
) {
memset(out, 0, nframes * sizeof(jack_default_audio_sample_t));
return nframes;
@@ -135,7 +141,7 @@ Session::ltc_tx_send_time_code_for_cycle (framepos_t start_frame, framepos_t end
/* all systems go. Now here's the plan:
*
* 1) check if fps has changed
- * 2) check direction of encoding, calc speed, resample existing buffer
+ * 2) check direction of encoding, calc speed, re-sample existing buffer
* 3) calculate frame and byte to send aligned to jack-period size
* 4) check if it's the frame/byte that is already in the queue
* 5) if (4) mismatch, re-calculate offset of LTC frame relative to period size
@@ -169,11 +175,20 @@ Session::ltc_tx_send_time_code_for_cycle (framepos_t start_frame, framepos_t end
#define SIGNUM(a) ( (a) < 0 ? -1 : 1)
bool speed_changed = false;
- // XXX
- //framepos_t cycle_start_frame = (current_speed < 0) ? (start_frame - ltc_latency.max) : (start_frame + ltc_latency.max);
+ /* use port latency compensation */
+#if 1
+ /* The generated timecode is offset by the port-latency,
+ * therefore the offset depends on the direction of transport.
+ */
+ framepos_t cycle_start_frame = (current_speed < 0) ? (start_frame + ltc_latency.max) : (start_frame - ltc_latency.max);
+#else
+ /* This comes in handy when testing sync - record output on an A3 track
+ * see also http://tracker.ardour.org/view.php?id=5073
+ */
framepos_t cycle_start_frame = start_frame;
+#endif
- /* cycle-start may become negative due to latency comensation */
+ /* cycle-start may become negative due to latency compensation */
if (cycle_start_frame < 0) { cycle_start_frame = 0; }
double new_ltc_speed = double(labs(end_frame - start_frame) * SIGNUM(current_speed)) / double(nframes);
@@ -187,9 +202,9 @@ Session::ltc_tx_send_time_code_for_cycle (framepos_t start_frame, framepos_t end
/* check ./libs/ardour/interpolation.cc CubicInterpolation::interpolate
* if target_speed != current_speed we should interpolate, too.
*
- * However, currenly in A3 target_speed == current_speed for each process cycle
+ * However, currency in A3 target_speed == current_speed for each process cycle
* (except for the sign and if target_speed > 8.0).
- * Besides, above speed calulation uses the difference (end_frame - start_frame).
+ * Besides, above speed calculation uses the difference (end_frame - start_frame).
* end_frame is calculated from 'frames_moved' which includes the interpolation.
* so we're good.
*/
@@ -227,8 +242,9 @@ Session::ltc_tx_send_time_code_for_cycle (framepos_t start_frame, framepos_t end
ltc_tx_reset();
}
- /* the timecode duration corresponding to the samples still in the buffer
- * here we use prev. speed to match the begining of this cycle for aligment.
+ /* the timecode duration corresponding to the samples that are still
+ * in the buffer. Here, the speed of previous cycle is used to calculate
+ * the alignment at the beginning of this cycle later.
*/
double poff = (ltc_buf_len - ltc_buf_off) * ltc_speed;
@@ -236,8 +252,8 @@ Session::ltc_tx_send_time_code_for_cycle (framepos_t start_frame, framepos_t end
/* we need to re-sample the existing buffer.
* "make space for the en-coder to catch up to the new speed"
*
- * since the LTC signal is a rect waveform we can simply squeeze it
- * by removing samples or duplicating /here and there/.
+ * since the LTC signal is a rectangular waveform we can simply squeeze it
+ * by removing samples or duplicating samples /here and there/.
*
* There may be a more elegant way to do this, in fact one could
* simply re-render the buffer using ltc_encoder_encode_byte()
@@ -300,7 +316,7 @@ Session::ltc_tx_send_time_code_for_cycle (framepos_t start_frame, framepos_t end
DEBUG_TRACE (DEBUG::LTC, string_compose("LTC TX2: transport speed %1.\n", ltc_speed));
- // (3) bit/sample aligment
+ // (3) bit/sample alignment
Timecode::Time tc_start;
framepos_t tc_sample_start;
@@ -320,17 +336,23 @@ Session::ltc_tx_send_time_code_for_cycle (framepos_t start_frame, framepos_t end
cycle_start_frame, tc_sample_start, soff));
- // (4) check if aligment matches
+ // (4) check if alignment matches
const double fptcf = frames_per_timecode_frame(); // convenient, used a lot below.
- double maxdiff;
- /* due to rounding error and variations in LTC-bit duration depending
- * on the speed, we can be off by +- speed samples.
- * during speed-changes we can acually ready += 2*speed audio-samples
- * in the cycle after the speed change. The average delta however is 0.
+ /* maximum difference of bit alignment in audio-samples.
+ *
+ * if transport and LTC generator differs more than this, the LTC
+ * generator will be re-initialized
+ *
+ * due to rounding error and variations in LTC-bit duration depending
+ * on the speed, it can be off by +- ltc_speed audio-samples.
+ * When the playback speed changes, it can actually reach +- 2 * ltc_speed
+ * in the cycle _after_ the speed changed. The average delta however is 0.
*/
- if (config.get_external_sync()) {
- maxdiff = fptcf; // TODO get slave max delta
+ double maxdiff;
+
+ if (config.get_external_sync() && slave()) {
+ maxdiff = slave()->resolution();
} else {
maxdiff = ceil(fabs(ltc_speed))*2.0;
}
@@ -357,8 +379,7 @@ Session::ltc_tx_send_time_code_for_cycle (framepos_t start_frame, framepos_t end
ltc_encoder_set_timecode(ltc_encoder, &tc);
/* workaround for libltc recognizing 29.97 and 30000/1001 as drop-frame TC.
- * in A3 only 30000/1001 is drop-frame and there are also other questionable
- * DF timecodes such as 24k/1001 and 25k/1001.
+ * In A3 30000/1001 or 30 fps can be drop-frame.
*/
LTCFrame ltcframe;
ltc_encoder_get_frame(ltc_encoder, &ltcframe);
@@ -393,16 +414,16 @@ Session::ltc_tx_send_time_code_for_cycle (framepos_t start_frame, framepos_t end
}
}
+ assert (cyc_off >= 0);
+
DEBUG_TRACE (DEBUG::LTC, string_compose("LTC TX5 restart encoder: soff %1 byte %2 cycoff %3\n",
soff, ltc_enc_byte, cyc_off));
- if (ltc_speed == 0) {
- /* don't bother to align non-moving loops */
- } else if (cyc_off > 0 && cyc_off <= nframes) {
+ if (cyc_off > 0 && cyc_off <= nframes) {
/* offset in this cycle */
txf= rint(cyc_off / fabs(ltc_speed));
memset(out, 0, cyc_off * sizeof(jack_default_audio_sample_t));
- } else if (cyc_off > 0) {
+ } else {
/* resync next cycle */
memset(out, 0, cyc_off * sizeof(jack_default_audio_sample_t));
return nframes;
@@ -471,9 +492,9 @@ Session::ltc_tx_send_time_code_for_cycle (framepos_t start_frame, framepos_t end
ltc_buf_len += enc_frames;
if (ltc_speed < 0)
- ltc_enc_cnt -= fptcf/10.0; //enc_frames * ltc_speed;
+ ltc_enc_cnt -= fptcf/10.0;
else
- ltc_enc_cnt += fptcf/10.0; //enc_frames * ltc_speed;
+ ltc_enc_cnt += fptcf/10.0;
if (ltc_speed >= 0) {
ltc_enc_byte = (ltc_enc_byte + 1)%10;