Add DSPLoadCalculator class to libardour
authorTim Mayberry <mojofunk@gmail.com>
Thu, 10 Sep 2015 01:44:39 +0000 (11:44 +1000)
committerTim Mayberry <mojofunk@gmail.com>
Thu, 10 Sep 2015 02:12:56 +0000 (12:12 +1000)
This is similar to the class in the PortaudioBackend but uses an average of the
values if raw load is under 80%

libs/ardour/ardour/dsp_load_calculator.h [new file with mode: 0644]
libs/ardour/dsp_load_calculator.cc [new file with mode: 0644]
libs/ardour/wscript

diff --git a/libs/ardour/ardour/dsp_load_calculator.h b/libs/ardour/ardour/dsp_load_calculator.h
new file mode 100644 (file)
index 0000000..911f1e3
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2015 Tim Mayberry <mojofunk@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef ARDOUR_DSP_LOAD_CALCULATOR_H
+#define ARDOUR_DSP_LOAD_CALCULATOR_H
+
+#include <stdint.h>
+#include <cassert>
+#include <algorithm>
+
+#include <pbd/ringbuffer.h>
+
+namespace ARDOUR {
+
+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_us(uint64_t max_time_us) {
+               assert(m_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();
+       }
+
+
+       uint64_t get_max_time_us() const { return m_max_time_us; }
+
+       void set_start_timestamp_us(uint64_t start_timestamp_us)
+       {
+               m_start_timestamp_us = start_timestamp_us;
+       }
+
+       void set_stop_timestamp_us(uint64_t stop_timestamp_us);
+
+       uint64_t elapsed_time_us()
+       {
+               return m_stop_timestamp_us - m_start_timestamp_us;
+       }
+
+       /**
+        * @return a decimal value between 0.0 and 1.0 representing the percentage
+        * of time spent between start and stop in proportion to the max expected time
+        * in microseconds(us).
+        */
+       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;
+               }
+               return m_dsp_load;
+       }
+private: // methods
+       static uint32_t max_value_history () { return 16; }
+
+private: // data
+       uint64_t m_max_time_us;
+       uint64_t m_start_timestamp_us;
+       uint64_t m_stop_timestamp_us;
+       float m_dsp_load;
+       RingBuffer<float> m_value_history;
+       uint32_t m_num_values;
+};
+
+} // namespace ARDOUR
+
+#endif // ARDOUR_DSP_LOAD_CALCULATOR_H
diff --git a/libs/ardour/dsp_load_calculator.cc b/libs/ardour/dsp_load_calculator.cc
new file mode 100644 (file)
index 0000000..d30b417
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2015 Tim Mayberry <mojofunk@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "ardour/dsp_load_calculator.h"
+
+namespace ARDOUR {
+
+void
+DSPLoadCalculator::set_stop_timestamp_us(uint64_t stop_timestamp_us)
+{
+       // We could only bother with calculations if a certain amount of time
+       // has passed, or the Raw DSP value is > X% different than last calc
+       // which would mean consistent overhead for small values of m_max_time_us
+
+       m_stop_timestamp_us = stop_timestamp_us;
+       float load = 0;
+
+       if (elapsed_time_us() > m_max_time_us) {
+               load = 1.0f;
+       } else {
+               load = elapsed_time_us() / (float)m_max_time_us;
+       }
+
+       assert(m_value_history.write_space() >= 1);
+
+       // push raw load value onto history
+       m_value_history.write(&load, 1);
+
+       // if load is under 80% use an average of past values
+       if (elapsed_time_us() < ((m_max_time_us * 80) / 100)) {
+
+               RingBuffer<float>::rw_vector vec;
+               m_value_history.get_read_vector(&vec);
+               uint32_t values_read = 0;
+               float dsp_accumulator = 0.0f;
+
+               // iterate through the read vectors accumulating the dsp load
+               for (unsigned int i = 0; i < vec.len[0]; ++i) {
+                       dsp_accumulator += vec.buf[0][i];
+                       values_read++;
+               }
+
+               for (unsigned int i = 0; i < vec.len[1]; ++i) {
+                       dsp_accumulator += vec.buf[1][i];
+                       values_read++;
+               }
+
+               load = dsp_accumulator / (float)values_read;
+
+               const float alpha = 0.2f * (m_max_time_us * 1e-6f);
+               m_dsp_load = m_dsp_load + alpha * (load - m_dsp_load) + 1e-12;
+
+       } else {
+               // Use raw load value otherwise 100% may never be indicated because of
+               // averaging/LPF etc
+               m_dsp_load = load;
+       }
+
+       if (m_value_history.read_space() >= m_num_values) {
+               // "remove" the oldest value
+               m_value_history.increment_read_idx(1);
+       }
+}
+
+} // namespace ARDOUR
index c0049b55fe85d8ced36ad2e62c95a0ed97e63851..becb2e117d91d6b5fe151fcf7939657a82096c2e 100644 (file)
@@ -65,6 +65,7 @@ libardour_sources = [
         'delivery.cc',
         'directory_names.cc',
         'diskstream.cc',
+        'dsp_load_calculator.cc',
         'element_import_handler.cc',
         'element_importer.cc',
         'engine_slave.cc',