diff --git a/libs/ardour/ardour/export_analysis.h b/libs/ardour/ardour/export_analysis.h index 7fc9b8fc58..b6e2e93126 100644 --- a/libs/ardour/ardour/export_analysis.h +++ b/libs/ardour/ardour/export_analysis.h @@ -49,6 +49,7 @@ namespace ARDOUR { memset (spectrum, 0, sizeof(spectrum)); memset (loudness_hist, 0, sizeof(loudness_hist)); memset (freq, 0, sizeof(freq)); + memset (limiter_pk, 0, sizeof(limiter_pk)); assert (sizeof(lgraph_i) == sizeof(lgraph_s)); assert (sizeof(lgraph_i) == sizeof(lgraph_m)); for (size_t i = 0; i < sizeof(lgraph_i) / sizeof (float); ++i) { @@ -84,6 +85,7 @@ namespace ARDOUR { memcpy (lgraph_i, other.lgraph_i, sizeof(lgraph_i)); memcpy (lgraph_s, other.lgraph_s, sizeof(lgraph_s)); memcpy (lgraph_m, other.lgraph_m, sizeof(lgraph_m)); + memcpy (limiter_pk, other.limiter_pk, sizeof(limiter_pk)); } float peak; @@ -109,6 +111,7 @@ namespace ARDOUR { float lgraph_i[800]; float lgraph_s[800]; float lgraph_m[800]; + float limiter_pk[800]; std::set truepeakpos[2]; // bins with >= -1dBTB }; diff --git a/libs/ardour/export_graph_builder.cc b/libs/ardour/export_graph_builder.cc index 0d12cf6a5c..4b8d5d7cfa 100644 --- a/libs/ardour/export_graph_builder.cc +++ b/libs/ardour/export_graph_builder.cc @@ -460,6 +460,7 @@ ExportGraphBuilder::SFC::SFC (ExportGraphBuilder &parent, FileSpec const & new_c config.filename->set_channel_config (config.channel_config); parent.add_analyser (config.filename->get_path (config.format), analyser); + limiter->set_result (analyser->result (true)); chunker->add_output (analyser); intermediate->add_output (chunker); @@ -510,6 +511,9 @@ ExportGraphBuilder::SFC::set_duration (samplecnt_t n_samples) if (analyser) { analyser->set_duration (n_samples); } + if (limiter) { + limiter->set_duration (n_samples); + } } void diff --git a/libs/audiographer/audiographer/general/analyser.h b/libs/audiographer/audiographer/general/analyser.h index c7b2a72b8c..b5b3d4c482 100644 --- a/libs/audiographer/audiographer/general/analyser.h +++ b/libs/audiographer/audiographer/general/analyser.h @@ -32,7 +32,7 @@ class LIBAUDIOGRAPHER_API Analyser : public LoudnessReader Analyser (float sample_rate, unsigned int channels, samplecnt_t bufsize, samplecnt_t n_samples); ~Analyser (); void process (ProcessContext const & c); - ARDOUR::ExportAnalysisPtr result (); + ARDOUR::ExportAnalysisPtr result (bool ptr = false); void set_duration (samplecnt_t n_samples); @@ -48,7 +48,8 @@ class LIBAUDIOGRAPHER_API Analyser : public LoudnessReader private: float fft_power_at_bin (const uint32_t b, const float norm) const; - ARDOUR::ExportAnalysis _result; + ARDOUR::ExportAnalysisPtr _rp; + ARDOUR::ExportAnalysis& _result; samplecnt_t _n_samples; samplecnt_t _pos; diff --git a/libs/audiographer/audiographer/general/limiter.h b/libs/audiographer/audiographer/general/limiter.h index 89dcfb189d..8e2f4c65cc 100644 --- a/libs/audiographer/audiographer/general/limiter.h +++ b/libs/audiographer/audiographer/general/limiter.h @@ -1,6 +1,8 @@ #ifndef AUDIOGRAPHER_LIMITER_H #define AUDIOGRAPHER_LIMITER_H +#include "ardour/export_analysis.h" + #include "audiographer/visibility.h" #include "audiographer/sink.h" #include "audiographer/utils/listed_source.h" @@ -23,16 +25,26 @@ public: void set_threshold (float dB); void set_release (float s); + void set_duration (samplecnt_t); + void set_result (ARDOUR::ExportAnalysisPtr); + void process (ProcessContext const& ctx); using Sink::process; private: + void stats (samplecnt_t); + bool _enabled; float* _buf; samplecnt_t _size; samplecnt_t _latency; - AudioGrapherDSP::Limiter _limiter; + samplecnt_t _cnt; + samplecnt_t _spp; + size_t _pos; + + ARDOUR::ExportAnalysisPtr _result; + AudioGrapherDSP::Limiter _limiter; }; } // namespace diff --git a/libs/audiographer/src/general/analyser.cc b/libs/audiographer/src/general/analyser.cc index 60a1c934bf..fcd0134ad9 100644 --- a/libs/audiographer/src/general/analyser.cc +++ b/libs/audiographer/src/general/analyser.cc @@ -25,9 +25,12 @@ const float Analyser::fft_range_db (120); // dB Analyser::Analyser (float sample_rate, unsigned int channels, samplecnt_t bufsize, samplecnt_t n_samples) : LoudnessReader (sample_rate, channels, bufsize) + , _rp (ARDOUR::ExportAnalysisPtr (new ARDOUR::ExportAnalysis)) + , _result (*_rp) , _n_samples (n_samples) , _pos (0) { + //printf ("NEW ANALYSER %p r:%.1f c:%d f:%ld l%ld\n", this, sample_rate, channels, bufsize, n_samples); assert (bufsize % channels == 0); assert (bufsize > 1); @@ -223,8 +226,12 @@ Analyser::process (ProcessContext const & ctx) } ARDOUR::ExportAnalysisPtr -Analyser::result () +Analyser::result (bool ptr_only) { + if (ptr_only) { + return _rp; + } + //printf ("PROCESSED %ld / %ld samples\n", _pos, _n_samples); if (_pos == 0 || _pos > _n_samples + 1) { return ARDOUR::ExportAnalysisPtr (); @@ -300,7 +307,7 @@ Analyser::result () } } - return ARDOUR::ExportAnalysisPtr (new ARDOUR::ExportAnalysis (_result)); + return _rp; } float diff --git a/libs/audiographer/src/general/limiter.cc b/libs/audiographer/src/general/limiter.cc index 1128f38284..439dcbf319 100644 --- a/libs/audiographer/src/general/limiter.cc +++ b/libs/audiographer/src/general/limiter.cc @@ -25,6 +25,9 @@ Limiter::Limiter (float sample_rate, unsigned int channels, samplecnt_t size) : _enabled (false) , _buf (0) , _size (0) + , _cnt (0) + , _spp (0) + , _pos (0) { _limiter.init (sample_rate, channels); @@ -63,6 +66,38 @@ Limiter::set_release (float s) _limiter.set_release (s); } +void +Limiter::set_duration (samplecnt_t s) +{ + if (_pos != 0 || !_result) { + return; + } + const size_t n_data = sizeof (ARDOUR::ExportAnalysis::limiter_pk) / sizeof (float); + _spp = ceilf (s / (float) n_data); +} + +void +Limiter::set_result (ARDOUR::ExportAnalysisPtr r) +{ + _result = r; +} + +void +Limiter::stats (samplecnt_t n_samples) +{ + if (!_result || _spp == 0) { + return; + } + _cnt += n_samples; + while (_cnt >= _spp) { + float peak, gmax, gmin; + _limiter.get_stats (&peak, &gmax, &gmin); + _cnt -= _spp; + assert (_pos < sizeof (ARDOUR::ExportAnalysis::limiter_pk) / sizeof (float)); + _result->limiter_pk[_pos++] = peak; + } +} + void Limiter::process (ProcessContext const& ctx) { const samplecnt_t n_samples = ctx.samples_per_channel (); @@ -75,6 +110,7 @@ void Limiter::process (ProcessContext const& ctx) } _limiter.process (n_samples, ctx.data (), _buf); + stats (n_samples); if (_latency > 0) { samplecnt_t ns = n_samples > _latency ? n_samples - _latency : 0; @@ -101,6 +137,7 @@ void Limiter::process (ProcessContext const& ctx) memset (_buf, 0, _size * sizeof (float)); samplecnt_t ns = _latency > bs ? bs : _latency; _limiter.process (ns, _buf, _buf); + //stats (ns); ProcessContext ctx_out (ctx, _buf, ns * n_channels); if (_latency == ns) { ctx_out.set_flag (ProcessContext::EndOfInput);