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
This commit is contained in:
Robin Gareus 2012-10-24 18:33:30 +00:00
parent ead6e3ade9
commit acb795980b

View file

@ -22,6 +22,7 @@
#include "ardour/session.h" #include "ardour/session.h"
#include "ardour/audioengine.h" #include "ardour/audioengine.h"
#include "ardour/audio_port.h" #include "ardour/audio_port.h"
#include "ardour/slave.h"
#include "i18n.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); out = (jack_default_audio_sample_t*) jack_port_get_buffer (ltcport->jack_port(), nframes);
if (!out) return 0; 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 /* TODO
* we can relax this a bit, JACK or sample-synced slaves should be fine. * decide which time-sources we can generated LTC from.
* test before allowing it, do the same for MTC generator in * Internal, JACK or sample-synced slaves should be fine.
* libs/ardour/session_midi.cc *
* */ *
// || config.get_external_sync() // XXX XXX || (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)); memset(out, 0, nframes * sizeof(jack_default_audio_sample_t));
return nframes; 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: /* all systems go. Now here's the plan:
* *
* 1) check if fps has changed * 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 * 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 * 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 * 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) #define SIGNUM(a) ( (a) < 0 ? -1 : 1)
bool speed_changed = false; bool speed_changed = false;
// XXX /* use port latency compensation */
//framepos_t cycle_start_frame = (current_speed < 0) ? (start_frame - ltc_latency.max) : (start_frame + ltc_latency.max); #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; 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; } if (cycle_start_frame < 0) { cycle_start_frame = 0; }
double new_ltc_speed = double(labs(end_frame - start_frame) * SIGNUM(current_speed)) / double(nframes); 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 /* check ./libs/ardour/interpolation.cc CubicInterpolation::interpolate
* if target_speed != current_speed we should interpolate, too. * 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). * (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. * end_frame is calculated from 'frames_moved' which includes the interpolation.
* so we're good. * 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(); ltc_tx_reset();
} }
/* the timecode duration corresponding to the samples still in the buffer /* the timecode duration corresponding to the samples that are still
* here we use prev. speed to match the begining of this cycle for aligment. * 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; 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. /* we need to re-sample the existing buffer.
* "make space for the en-coder to catch up to the new speed" * "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 * since the LTC signal is a rectangular waveform we can simply squeeze it
* by removing samples or duplicating /here and there/. * by removing samples or duplicating samples /here and there/.
* *
* There may be a more elegant way to do this, in fact one could * There may be a more elegant way to do this, in fact one could
* simply re-render the buffer using ltc_encoder_encode_byte() * 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)); 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; Timecode::Time tc_start;
framepos_t tc_sample_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)); 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. const double fptcf = frames_per_timecode_frame(); // convenient, used a lot below.
/* 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.
*/
double maxdiff; double maxdiff;
/* due to rounding error and variations in LTC-bit duration depending if (config.get_external_sync() && slave()) {
* on the speed, we can be off by +- speed samples. maxdiff = slave()->resolution();
* during speed-changes we can acually ready += 2*speed audio-samples
* in the cycle after the speed change. The average delta however is 0.
*/
if (config.get_external_sync()) {
maxdiff = fptcf; // TODO get slave max delta
} else { } else {
maxdiff = ceil(fabs(ltc_speed))*2.0; 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); ltc_encoder_set_timecode(ltc_encoder, &tc);
/* workaround for libltc recognizing 29.97 and 30000/1001 as drop-frame 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 * In A3 30000/1001 or 30 fps can be drop-frame.
* DF timecodes such as 24k/1001 and 25k/1001.
*/ */
LTCFrame ltcframe; LTCFrame ltcframe;
ltc_encoder_get_frame(ltc_encoder, &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", DEBUG_TRACE (DEBUG::LTC, string_compose("LTC TX5 restart encoder: soff %1 byte %2 cycoff %3\n",
soff, ltc_enc_byte, cyc_off)); soff, ltc_enc_byte, cyc_off));
if (ltc_speed == 0) { if (cyc_off > 0 && cyc_off <= nframes) {
/* don't bother to align non-moving loops */
} else if (cyc_off > 0 && cyc_off <= nframes) {
/* offset in this cycle */ /* offset in this cycle */
txf= rint(cyc_off / fabs(ltc_speed)); txf= rint(cyc_off / fabs(ltc_speed));
memset(out, 0, cyc_off * sizeof(jack_default_audio_sample_t)); memset(out, 0, cyc_off * sizeof(jack_default_audio_sample_t));
} else if (cyc_off > 0) { } else {
/* resync next cycle */ /* resync next cycle */
memset(out, 0, cyc_off * sizeof(jack_default_audio_sample_t)); memset(out, 0, cyc_off * sizeof(jack_default_audio_sample_t));
return nframes; 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; ltc_buf_len += enc_frames;
if (ltc_speed < 0) if (ltc_speed < 0)
ltc_enc_cnt -= fptcf/10.0; //enc_frames * ltc_speed; ltc_enc_cnt -= fptcf/10.0;
else else
ltc_enc_cnt += fptcf/10.0; //enc_frames * ltc_speed; ltc_enc_cnt += fptcf/10.0;
if (ltc_speed >= 0) { if (ltc_speed >= 0) {
ltc_enc_byte = (ltc_enc_byte + 1)%10; ltc_enc_byte = (ltc_enc_byte + 1)%10;