--- /dev/null
+#include "audio_clip.h"
+
+#include <math.h>
+
+using namespace std;
+using namespace std::chrono;
+
+void AudioClip::clear()
+{
+ lock_guard<mutex> lock(mu);
+ vals.clear();
+}
+
+void AudioClip::add_audio(const float *samples, size_t num_samples, double sample_rate, std::chrono::steady_clock::time_point frame_time)
+{
+ lock_guard<mutex> lock(mu);
+ if (!vals.empty() && sample_rate != this->sample_rate) {
+ vals.clear();
+ }
+ if (vals.empty()) {
+ first_sample = frame_time;
+ }
+ this->sample_rate = sample_rate;
+ vals.insert(vals.end(), samples, samples + num_samples);
+}
+
+double AudioClip::get_length_seconds() const
+{
+ lock_guard<mutex> lock(mu);
+ if (vals.empty()) {
+ return 0.0;
+ }
+
+ return double(vals.size()) / sample_rate;
+}
+
+
+unique_ptr<pair<float, float>[]> AudioClip::get_min_max_peaks(unsigned width) const
+{
+ unique_ptr<pair<float, float>[]> min_max(new pair<float, float>[width]);
+ for (unsigned x = 0; x < width; ++x) {
+ min_max[x].first = min_max[x].second = 0.0 / 0.0; // NaN.
+ }
+
+ lock_guard<mutex> lock(mu);
+ for (size_t i = 0; i < vals.size(); ++i) {
+ // We display one second.
+ int x = lrint(i * (double(width) / sample_rate));
+ if (x < 0 || x >= int(width)) continue;
+ if (isnan(min_max[x].first)) {
+ min_max[x].first = min_max[x].second = 0.0;
+ }
+ min_max[x].first = min(min_max[x].first, vals[i]);
+ min_max[x].second = max(min_max[x].second, vals[i]);
+ }
+
+ return min_max;
+}