From 149b1b3690992a0a5a954b2fa3a010ae7b16c20b Mon Sep 17 00:00:00 2001 From: itsmattkc <34096995+itsmattkc@users.noreply.github.com> Date: Tue, 27 Sep 2022 21:17:37 -0700 Subject: [PATCH] audiowaveformcache: improve passthrough system --- app/common/timerange.h | 11 +++ app/render/audiowaveformcache.cpp | 121 +++++++++++++----------------- app/render/audiowaveformcache.h | 55 +++++--------- 3 files changed, 80 insertions(+), 107 deletions(-) diff --git a/app/common/timerange.h b/app/common/timerange.h index b6235f9b8..8fc55872e 100644 --- a/app/common/timerange.h +++ b/app/common/timerange.h @@ -126,6 +126,17 @@ public: return false; } + bool OverlapsWith(const TimeRange& r, bool in_inclusive = true, bool out_inclusive = true) const + { + for (const TimeRange &range : array_) { + if (range.OverlapsWith(r, in_inclusive, out_inclusive)) { + return true; + } + } + + return false; + } + bool isEmpty() const { return array_.isEmpty(); diff --git a/app/render/audiowaveformcache.cpp b/app/render/audiowaveformcache.cpp index 5ed1ee280..4f9870759 100644 --- a/app/render/audiowaveformcache.cpp +++ b/app/render/audiowaveformcache.cpp @@ -22,113 +22,94 @@ namespace olive { +#define super PlaybackCache + AudioWaveformCache::AudioWaveformCache(QObject *parent) : - PlaybackCache{parent} + super{parent} { + waveforms_ = std::make_shared(); } void AudioWaveformCache::WriteWaveform(const TimeRange &range, const TimeRangeList &valid_ranges, const AudioVisualWaveform *waveform) { // Write each valid range to the segments foreach (const TimeRange& r, valid_ranges) { -#ifdef AVW_USE_LIST - // Write visual - TimeRangeList::util_remove(&waveforms_, r); - if (waveform) { - TimeRangeWithWaveform wv = r; - rational local_start = r.in() - range.in(); - if (local_start != 0) { - wv.waveform = waveform->Mid(local_start, r.length()); - } else { - wv.waveform = *waveform; - } - waveforms_.append(wv); + waveforms_->OverwriteSums(*waveform, r.in(), r.in() - range.in(), r.length()); } -#else - if (waveform) { - waveforms_.OverwriteSums(*waveform, r.in(), r.in() - range.in(), r.length()); - } -#endif Validate(r); } } +void DrawSubRect(QPainter *painter, const QRect &rect, const double &scale, const TimeRange &wave_range, const AudioVisualWaveform &waveform, const TimeRange &subrange) +{ + // Find start time of passthrough + TimeRange intersect = wave_range.Intersected(subrange); + + // Create new rect that starts at the offset of pass_start from start_time + // Set rect width to either length of passthrough or until the end + QRect pass_rect(rect.x() + (intersect.in() - wave_range.in()).toDouble() * scale, + rect.y(), + intersect.length().toDouble() * scale, + rect.height()); + + // Draw waveform with this info + AudioVisualWaveform::DrawWaveform(painter, pass_rect, scale, waveform, intersect.in()); +} + void AudioWaveformCache::Draw(QPainter *painter, const QRect &rect, const double &scale, const rational &start_time) const { - rational end = start_time + rational::fromDouble(rect.width() / scale); - TimeRange draw_range(start_time, end); + if (!passthroughs_.empty()) { + TimeRange wave_range(start_time, start_time + rational::fromDouble(rect.width() / scale)); + TimeRangeList draw_range = {wave_range}; + for (const WaveformPassthrough &p : passthroughs_) { + if (draw_range.OverlapsWith(p, true, false)) { + DrawSubRect(painter, rect, scale, wave_range, *p.waveform, p); -#ifdef AVW_USE_LIST - foreach (const TimeRangeWithWaveform &wv, waveforms_) { - if (wv.OverlapsWith(draw_range)) { - rational substart = std::max(wv.in(), draw_range.in()); - rational subend = std::min(wv.out(), draw_range.out()); - - QRect subrect = rect; - subrect.setLeft(subrect.left() + (substart - draw_range.in()).toDouble()*scale); - subrect.setWidth((subend - substart).toDouble()*scale); - - rational local_start = substart - wv.in(); - AudioVisualWaveform::DrawWaveform(painter, subrect, scale, wv.waveform, local_start); + // Remove this range + draw_range.remove(p); + } } + + for (const TimeRange &r : draw_range) { + DrawSubRect(painter, rect, scale, wave_range, *waveforms_, r); + } + } else { + AudioVisualWaveform::DrawWaveform(painter, rect, scale, *waveforms_, start_time); } -#else - AudioVisualWaveform::DrawWaveform(painter, rect, scale, waveforms_, start_time); -#endif } AudioVisualWaveform::Sample AudioWaveformCache::GetSummaryFromTime(const rational &start, const rational &length) const { -#ifdef AVW_USE_LIST - QMap sample; - - TimeRange acquire(start, start+length); - foreach (const TimeRangeWithWaveform &wv, waveforms_) { - if (wv.OverlapsWith(acquire)) { - TimeRange this_range = wv.Intersected(acquire); - auto sum = wv.waveform.GetSummaryFromTime(this_range.in() - wv.in(), this_range.length()); - sample.insert(this_range.in(), sum); - } - } - - AudioVisualWaveform::Sample result; - - for (auto it=sample.cbegin(); it!=sample.cend(); it++) { - result.insert(result.end(), it.value().begin(), it.value().end()); - } - - return result; -#else - return waveforms_.GetSummaryFromTime(start, length); -#endif + return waveforms_->GetSummaryFromTime(start, length); } rational AudioWaveformCache::length() const { -#ifdef AVW_USE_LIST - rational len = 0; - - foreach (const TimeRangeWithWaveform &wv, waveforms_) { - len = std::max(len, wv.out()); - } - - return len; -#else - return waveforms_.length(); -#endif + return waveforms_->length(); } void AudioWaveformCache::SetPassthrough(PlaybackCache *cache) { AudioWaveformCache *c = static_cast(cache); - waveforms_ = c->waveforms_; + for (const TimeRange &r : c->GetValidatedRanges()) { - Validate(r); + WaveformPassthrough t = r; + t.waveform = c->waveforms_; + passthroughs_.append(t); } + passthroughs_.append(c->passthroughs_); + SetParameters(c->GetParameters()); SetSavingEnabled(c->IsSavingEnabled()); } +void AudioWaveformCache::InvalidateEvent(const TimeRange& range) +{ + TimeRangeList::util_remove(&passthroughs_, range); + + super::InvalidateEvent(range); +} + } diff --git a/app/render/audiowaveformcache.h b/app/render/audiowaveformcache.h index a1a6dcfe5..feeeacb63 100644 --- a/app/render/audiowaveformcache.h +++ b/app/render/audiowaveformcache.h @@ -24,8 +24,6 @@ #include "audio/audiovisualwaveform.h" #include "playbackcache.h" -//#define AVW_USE_LIST - namespace olive { class AudioWaveformCache : public PlaybackCache @@ -40,7 +38,7 @@ public: void SetParameters(const AudioParams &p) { params_ = p; - waveforms_.set_channel_count(p.channel_count()); + waveforms_->set_channel_count(p.channel_count()); } void Draw(QPainter* painter, const QRect &rect, const double &scale, const rational &start_time) const; @@ -51,45 +49,28 @@ public: virtual void SetPassthrough(PlaybackCache *cache) override; +protected: + virtual void InvalidateEvent(const TimeRange& range); + private: -#ifdef AVW_USE_LIST - class TimeRangeWithWaveform : public TimeRange - { - public: - TimeRangeWithWaveform() = default; - TimeRangeWithWaveform(const TimeRange &r) : - TimeRange(r) - { - } + using WaveformPtr = std::shared_ptr; - void set_in(const rational& in) - { - waveform.TrimIn(in - this->in()); - TimeRange::set_in(in); - } - - void set_out(const rational& out) - { - waveform.Resize(out - this->in()); - TimeRange::set_out(out); - } - - void set_range(const rational& in, const rational& out) - { - waveform.TrimRange(in, out-in); - TimeRange::set_range(in, out); - } - - AudioVisualWaveform waveform; - }; - - QVector waveforms_; -#else - AudioVisualWaveform waveforms_; -#endif + WaveformPtr waveforms_; AudioParams params_; + class WaveformPassthrough : public TimeRange + { + public: + WaveformPassthrough(const TimeRange &r) : + TimeRange(r) + {} + + WaveformPtr waveform; + }; + + QVector passthroughs_; + }; }