X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fardour%2Fdsp_load_calculator.h;h=88b327bb300ef8ab85853df680d900aca92248aa;hb=7a524285385d4581ad3f1e085629379e32f82fda;hp=0fed1db7a44b2991a0979346e4cd0c3791d275c3;hpb=1a6c08dcfc07b7254dd2ac4470a363a1a0f94461;p=ardour.git diff --git a/libs/ardour/ardour/dsp_load_calculator.h b/libs/ardour/ardour/dsp_load_calculator.h index 0fed1db7a4..88b327bb30 100644 --- a/libs/ardour/ardour/dsp_load_calculator.h +++ b/libs/ardour/ardour/dsp_load_calculator.h @@ -19,53 +19,73 @@ #ifndef ARDOUR_DSP_LOAD_CALCULATOR_H #define ARDOUR_DSP_LOAD_CALCULATOR_H +#include #include #include #include -#include - -#include "ardour/libardour_visibility.h" - namespace ARDOUR { -class LIBARDOUR_API DSPLoadCalculator { +class DSPLoadCalculator { public: DSPLoadCalculator() : m_max_time_us(0) , m_start_timestamp_us(0) , m_stop_timestamp_us(0) , m_dsp_load(0) - , m_value_history (max_value_history()) - , m_num_values(0) { } + void set_max_time(double samplerate, uint32_t period_size) { + m_max_time_us = period_size * 1e6 / samplerate; + } + void set_max_time_us(uint64_t max_time_us) { - assert(m_max_time_us != 0); + assert(max_time_us != 0); m_max_time_us = max_time_us; - - // Use average of last 1/4 second of values so responsiveness - // remains consistent independent of max time - uint32_t max_dsp_samples_per_qtr_second = (250000 / m_max_time_us); - m_num_values = - std::min(max_value_history() - 1, max_dsp_samples_per_qtr_second); - - m_value_history.reset(); } + int64_t get_max_time_us() const { return m_max_time_us; } - uint64_t get_max_time_us() const { return m_max_time_us; } - - void set_start_timestamp_us(uint64_t start_timestamp_us) + void set_start_timestamp_us(int64_t start_timestamp_us) { m_start_timestamp_us = start_timestamp_us; } - void set_stop_timestamp_us(uint64_t stop_timestamp_us); + void set_stop_timestamp_us(int64_t stop_timestamp_us) + { + m_stop_timestamp_us = stop_timestamp_us; + + /* querying the performance counter can fail occasionally (-1). + * Also on some multi-core systems, timers are CPU specific and not + * synchronized. We assume they differ more than a few milliseconds + * (4 * nominal cycle time) and simply ignore cases where the + * execution switches cores. + */ + if (m_start_timestamp_us < 0 || m_stop_timestamp_us < 0 || + m_start_timestamp_us > m_stop_timestamp_us || + elapsed_time_us() > max_timer_error_us()) { + return; + } + +#ifndef NDEBUG + const bool calc_avg_load = NULL != getenv("AVGLOAD"); +#else + const bool calc_avg_load = false; +#endif + + const float load = (float) elapsed_time_us() / (float)m_max_time_us; + if ((calc_avg_load && load > .95f) || (!calc_avg_load && (load > m_dsp_load || load > 1.f))) { + m_dsp_load = load; + } else { + const float alpha = 0.2f * (m_max_time_us * 1e-6f); + m_dsp_load = std::min (1.f, m_dsp_load); + m_dsp_load += alpha * (load - m_dsp_load) + 1e-12; + } + } - uint64_t elapsed_time_us() + int64_t elapsed_time_us() { return m_stop_timestamp_us - m_start_timestamp_us; } @@ -77,24 +97,32 @@ public: */ float get_dsp_load() const { - if (m_dsp_load > m_max_time_us) { - return 1.0f; - } - if (m_dsp_load < 0.0f) { - return 0.0f; - } + assert (m_dsp_load >= 0.f); // since stop > start is assured this cannot happen. + return std::min (1.f, m_dsp_load); + } + + /** + * @return an unbound value representing the percentage of time spent between + * start and stop in proportion to the max expected time in microseconds(us). + * This is useful for cases to estimate overload (e.g. Dummy backend) + */ + float get_dsp_load_unbound() const + { + assert (m_dsp_load >= 0.f); return m_dsp_load; } -private: // methods - static uint32_t max_value_history () { return 16; } + + /** + * The maximum error in timestamp values that will be tolerated before the + * current dsp load sample will be ignored + */ + int64_t max_timer_error_us() { return 4 * m_max_time_us; } private: // data - uint64_t m_max_time_us; - uint64_t m_start_timestamp_us; - uint64_t m_stop_timestamp_us; + int64_t m_max_time_us; + int64_t m_start_timestamp_us; + int64_t m_stop_timestamp_us; float m_dsp_load; - RingBuffer m_value_history; - uint32_t m_num_values; }; } // namespace ARDOUR