From e8644654c21c47d71d1cc35d96d24a24d9e0d7e6 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Tue, 10 Sep 2024 18:10:23 +0200 Subject: [PATCH] Prepare to filter incoming LTC --- libs/ardour/ardour/transport_master.h | 13 +++++- libs/ardour/ltc_slave.cc | 65 ++++++++++++++++++++------- 2 files changed, 60 insertions(+), 18 deletions(-) diff --git a/libs/ardour/ardour/transport_master.h b/libs/ardour/ardour/transport_master.h index cdf9979b92..9752636469 100644 --- a/libs/ardour/ardour/transport_master.h +++ b/libs/ardour/ardour/transport_master.h @@ -613,7 +613,7 @@ public: void create_port (); private: - void parse_ltc (const pframes_t, const Sample* const, const samplecnt_t); + void parse_ltc (const pframes_t, Sample const*, samplecnt_t); void process_ltc (samplepos_t const); void init_dll (samplepos_t, int32_t); bool detect_discontinuity (LTCFrameExt*, int, bool); @@ -643,6 +643,17 @@ private: PBD::ScopedConnection port_connection; PBD::ScopedConnectionList session_connections; LatencyRange ltc_slave_latency; + + + struct Biquad { + void reset () { z1 = z2 = 0;} + float z1, z2; + double a1, a2, b0, b1, b2; + }; + + bool _filter_enable; + Biquad _lpf; + Biquad _hpf; }; class LIBARDOUR_API MIDIClock_TransportMaster : public TransportMaster, public TransportMasterViaMIDI diff --git a/libs/ardour/ltc_slave.cc b/libs/ardour/ltc_slave.cc index d6da90b2a5..a13f7c9467 100644 --- a/libs/ardour/ltc_slave.cc +++ b/libs/ardour/ltc_slave.cc @@ -27,6 +27,7 @@ #include "pbd/pthread_utils.h" #include "ardour/debug.h" +#include "ardour/dsp_filter.h" #include "ardour/profile.h" #include "ardour/transport_master.h" #include "ardour/session.h" @@ -58,6 +59,7 @@ LTC_TransportMaster::LTC_TransportMaster (std::string const & name) , ltc_detect_fps_max (0) , sync_lock_broken (false) , samples_per_timecode_frame (0) + , _filter_enable (false) { memset (&prev_frame, 0, sizeof(LTCFrameExt)); @@ -97,6 +99,17 @@ LTC_TransportMaster::set_session (Session *s) decoder = ltc_decoder_create((int) samples_per_ltc_frame, 128 /*queue size*/); + DSP::Biquad bq (AudioEngine::instance()->sample_rate()); + bq.compute (DSP::Biquad::LowPass, 3500, 0.9, 0); + bq.coefficients (_lpf.a1, _lpf.a2, _lpf.b0, _lpf.b1, _lpf.b2); + bq.compute (DSP::Biquad::HighPass, 100, 0.707, 0); + bq.coefficients (_hpf.a1, _hpf.a2, _hpf.b0, _hpf.b1, _hpf.b2); + _lpf.reset (); + _hpf.reset (); + + // TODO add a per master preference to enable filter (and set gain) + //_filter_enable = true; + parse_timecode_offset(); reset (true); @@ -104,6 +117,8 @@ LTC_TransportMaster::set_session (Session *s) _session->config.ParameterChanged.connect_same_thread (session_connections, boost::bind (<C_TransportMaster::parameter_changed, this, _1)); _session->LatencyUpdated.connect_same_thread (session_connections, boost::bind (<C_TransportMaster::resync_latency, this, _1)); + } else { + _filter_enable = false; } } @@ -209,6 +224,8 @@ LTC_TransportMaster::resync_latency (bool playback) if (old != ltc_slave_latency.max) { sync_lock_broken = false; } + _lpf.reset (); + _hpf.reset (); } void @@ -231,26 +248,40 @@ LTC_TransportMaster::reset (bool with_position) } void -LTC_TransportMaster::parse_ltc (const ARDOUR::pframes_t nframes, const Sample* const in, const ARDOUR::samplecnt_t posinfo) +LTC_TransportMaster::parse_ltc (pframes_t const n_samples, Sample const* in, samplecnt_t posinfo) { - pframes_t i; - unsigned char sound[8192]; + pframes_t remain = n_samples; - if (nframes > 8192) { - /* TODO warn once or wrap, loop conversion below - * does jack/A3 support > 8192 spp anyway? - */ - return; - } + bool const fe = _filter_enable; + float const gain = 127.0; // relative to signed 8bit, 127.0 == 0dB - for (i = 0; i < nframes; i++) { - const int snd=(int) rint ((127.0*in[i])+128.0); - sound[i] = (unsigned char) (snd&0xff); - } - - ltc_decoder_write (decoder, sound, nframes, posinfo); - - return; + while (remain > 0) { + ltcsnd_sample_t sound[8192]; + pframes_t c = std::min (remain, 8192); + if (fe) { + for (pframes_t i = 0; i < c; ++i) { + /* LPF */ + float xn = *in++; + float z = _lpf.b0 * xn + _lpf.z1; + _lpf.z1 = _lpf.b1 * xn - _lpf.a1 * z + _lpf.z2; + _lpf.z2 = _lpf.b2 * xn - _lpf.a2 * z; + /* HPF */ + xn = z; + z = _hpf.b0 * xn + _hpf.z1; + _hpf.z1 = _hpf.b1 * xn - _hpf.a1 * z + _hpf.z2; + _hpf.z2 = _hpf.b2 * xn - _hpf.a2 * z; + /* convert */ + sound[i] = 128 + min (127, max (-127, gain * z)); + } + } else { + for (pframes_t i = 0; i < c; ++i) { + sound[i] = 128 + min (127, max (-127, gain * (*in++))); + } + } + ltc_decoder_write (decoder, sound, c, posinfo); + posinfo += c; + remain -= c; + } } bool