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:
parent
ead6e3ade9
commit
acb795980b
|
@ -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.
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
if (config.get_external_sync()) {
|
||||
maxdiff = fptcf; // TODO get slave max delta
|
||||
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, <cframe);
|
||||
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue
Block a user