audiowaveformcache: improve passthrough system

This commit is contained in:
itsmattkc
2022-09-27 21:17:37 -07:00
parent a29fa4bc4d
commit 149b1b3690
3 changed files with 80 additions and 107 deletions
+11
View File
@@ -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();
+51 -70
View File
@@ -22,113 +22,94 @@
namespace olive {
#define super PlaybackCache
AudioWaveformCache::AudioWaveformCache(QObject *parent) :
PlaybackCache{parent}
super{parent}
{
waveforms_ = std::make_shared<AudioVisualWaveform>();
}
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<rational, AudioVisualWaveform::Sample> 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<AudioWaveformCache*>(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);
}
}
+18 -37
View File
@@ -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<AudioVisualWaveform>;
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<TimeRangeWithWaveform> waveforms_;
#else
AudioVisualWaveform waveforms_;
#endif
WaveformPtr waveforms_;
AudioParams params_;
class WaveformPassthrough : public TimeRange
{
public:
WaveformPassthrough(const TimeRange &r) :
TimeRange(r)
{}
WaveformPtr waveform;
};
QVector<WaveformPassthrough> passthroughs_;
};
}