+ return;
+ }
+
+ if (ltc_speed == 0 && new_ltc_speed != 0) {
+ DEBUG_TRACE (DEBUG::LTC, "LTC TX2: transport started rolling - reset\n");
+ ltc_tx_reset();
+ }
+
+ /* 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;
+
+ if (speed_changed && new_ltc_speed != 0) {
+ /* 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 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()
+ * but that'd require some timecode offset buffer magic,
+ * which is left for later..
+ */
+
+ double oldbuflen = (double)(ltc_buf_len - ltc_buf_off);
+ double newbuflen = (double)(ltc_buf_len - ltc_buf_off) * fabs(ltc_speed / new_ltc_speed);
+
+ DEBUG_TRACE (DEBUG::LTC, string_compose("LTC TX2: bufOld %1 bufNew %2 | diff %3\n",
+ (ltc_buf_len - ltc_buf_off), newbuflen, newbuflen - oldbuflen
+ ));
+
+ double bufrspdiff = rint(newbuflen - oldbuflen);
+
+ if (abs(bufrspdiff) > newbuflen || abs(bufrspdiff) > oldbuflen) {
+ DEBUG_TRACE (DEBUG::LTC, "LTC TX2: resampling buffer would destroy information.\n");
+ ltc_tx_reset();
+ poff = 0;
+ } else if (bufrspdiff != 0 && newbuflen > oldbuflen) {
+ int incnt = 0;
+ double samples_to_insert = ceil(newbuflen - oldbuflen);
+ double avg_distance = newbuflen / samples_to_insert;
+ DEBUG_TRACE (DEBUG::LTC, string_compose("LTC TX2: resample buffer insert: %1\n", samples_to_insert));
+
+ for (int rp = ltc_buf_off; rp < ltc_buf_len - 1; ++rp) {
+ const int ro = rp - ltc_buf_off;
+ if (ro < (incnt*avg_distance)) continue;
+ const ltcsnd_sample_t v1 = ltc_enc_buf[rp];
+ const ltcsnd_sample_t v2 = ltc_enc_buf[rp+1];
+ if (v1 != v2 && ro < ((incnt+1)*avg_distance)) continue;
+ memmove(<c_enc_buf[rp+1], <c_enc_buf[rp], ltc_buf_len-rp);
+ incnt++;
+ ltc_buf_len++;
+ }
+ } else if (bufrspdiff != 0 && newbuflen < oldbuflen) {
+ double samples_to_remove = ceil(oldbuflen - newbuflen);
+ DEBUG_TRACE (DEBUG::LTC, string_compose("LTC TX2: resample buffer - remove: %1\n", samples_to_remove));
+ if (oldbuflen <= samples_to_remove) {
+ ltc_buf_off = ltc_buf_len= 0;
+ } else {
+ double avg_distance = newbuflen / samples_to_remove;
+ int rmcnt = 0;
+ for (int rp = ltc_buf_off; rp < ltc_buf_len - 1; ++rp) {
+ const int ro = rp - ltc_buf_off;
+ if (ro < (rmcnt*avg_distance)) continue;
+ const ltcsnd_sample_t v1 = ltc_enc_buf[rp];
+ const ltcsnd_sample_t v2 = ltc_enc_buf[rp+1];
+ if (v1 != v2 && ro < ((rmcnt+1)*avg_distance)) continue;
+ memmove(<c_enc_buf[rp], <c_enc_buf[rp+1], ltc_buf_len-rp-1);
+ ltc_buf_len--;
+ rmcnt++;
+ }
+ }
+ }