timeline: automate waveform resizing

Now each UndoCommand won't have to handle it (unless it can introduce
specific optimizations).
This commit is contained in:
itsmattkc
2020-06-01 14:54:14 +10:00
parent a62960ecc0
commit 1fce380cc6
7 changed files with 103 additions and 72 deletions
+23 -7
View File
@@ -69,8 +69,8 @@ void AudioVisualWaveform::OverwriteSamples(SampleBufferPtr samples, int sample_r
qWarning() << "Failed to write samples - channel count is zero";
}
int start_index = channels_ * qFloor(kSumSampleRate * start.toDouble());
int samples_length = channels_ * qFloor(kSumSampleRate * (static_cast<double>(samples->sample_count()) / static_cast<double>(sample_rate)));
int start_index = time_to_samples(start);
int samples_length = time_to_samples(static_cast<double>(samples->sample_count()) / static_cast<double>(sample_rate));
int end_index = start_index + samples_length;
if (data_.size() < end_index) {
@@ -93,7 +93,21 @@ void AudioVisualWaveform::OverwriteSamples(SampleBufferPtr samples, int sample_r
}
}
AudioVisualWaveform AudioVisualWaveform::Cut(const rational &time)
void AudioVisualWaveform::OverwriteSums(const AudioVisualWaveform &sums, const rational &start)
{
int start_index = time_to_samples(start);
int end_index = start_index + sums.data_.size();
if (data_.size() < end_index) {
data_.resize(end_index);
}
memcpy(&data_[start_index],
sums.data_.constData(),
sums.data_.size() * sizeof(SamplePerChannel));
}
AudioVisualWaveform AudioVisualWaveform::Mid(const rational &time) const
{
int sample_index = time_to_samples(time);
@@ -101,9 +115,6 @@ AudioVisualWaveform AudioVisualWaveform::Cut(const rational &time)
AudioVisualWaveform copy = *this;
copy.data_ = data_.mid(sample_index);
// Chop the latter section off too
data_.resize(sample_index);
return copy;
}
@@ -270,7 +281,12 @@ void AudioVisualWaveform::DrawWaveform(QPainter *painter, const QRect& rect, con
int AudioVisualWaveform::time_to_samples(const rational &time) const
{
return qFloor(time.toDouble() * kSumSampleRate) * channels_;
return time_to_samples(time.toDouble());
}
int AudioVisualWaveform::time_to_samples(const double &time) const
{
return qFloor(time * kSumSampleRate) * channels_;
}
template<typename T>
+3 -1
View File
@@ -69,8 +69,9 @@ public:
void AddSum(const float* samples, int nb_samples, int nb_channels);
void OverwriteSamples(SampleBufferPtr samples, int sample_rate, const rational& start);
void OverwriteSums(const AudioVisualWaveform& sums, const rational& start);
AudioVisualWaveform Cut(const rational& time);
AudioVisualWaveform Mid(const rational& time) const;
void Append(const AudioVisualWaveform& waveform);
void TrimIn(const rational& time);
void TrimOut(const rational& time);
@@ -98,6 +99,7 @@ private:
static void ClampMinMax(SamplePerChannel &sum, T value);
int time_to_samples(const rational& time) const;
int time_to_samples(const double& time) const;
int channels_ = 0;
+19 -2
View File
@@ -101,7 +101,11 @@ void Block::set_length_and_media_out(const rational &length)
return;
}
length_input_->set_standard_value(QVariant::fromValue(length));
rational old_length = this->length();
set_length_internal(length);
LengthChangedEvent(old_length, length, Timeline::kTrimOut);
}
void Block::set_length_and_media_in(const rational &length)
@@ -115,8 +119,12 @@ void Block::set_length_and_media_in(const rational &length)
// Calculate media_in adjustment
set_media_in(media_in() + (this->length() - length) * speed());
rational old_length = this->length();
// Set the length without setting media out
set_length_and_media_out(length);
set_length_internal(length);
LengthChangedEvent(old_length, length, Timeline::kTrimIn);
}
Block *Block::previous()
@@ -246,6 +254,15 @@ QList<NodeInput *> Block::GetInputsToHash() const
return inputs;
}
void Block::LengthChangedEvent(const rational &, const rational &, const Timeline::MovementMode &)
{
}
void Block::set_length_internal(const rational &length)
{
length_input_->set_standard_value(QVariant::fromValue(length));
}
void Block::LengthInputChanged()
{
emit LengthChanged(length());
+7
View File
@@ -22,6 +22,7 @@
#define BLOCK_H
#include "node/node.h"
#include "timeline/timelinecommon.h"
OLIVE_NAMESPACE_ENTER
@@ -130,10 +131,16 @@ protected:
virtual QList<NodeInput*> GetInputsToHash() const override;
virtual void LengthChangedEvent(const rational& old_length,
const rational& new_length,
const Timeline::MovementMode& mode);
Block* previous_;
Block* next_;
private:
void set_length_internal(const rational &length);
NodeInput* name_input_;
NodeInput* length_input_;
NodeInput* media_in_input_;
+20
View File
@@ -59,6 +59,26 @@ NodeInput *ClipBlock::texture_input() const
return texture_input_;
}
void ClipBlock::LengthChangedEvent(const rational &old_length, const rational &new_length, const Timeline::MovementMode &mode)
{
// Positive if made longer, negative if made shorter
rational diff = new_length - old_length;
if (diff < rational()) {
if (mode == Timeline::kTrimIn) {
waveform().TrimIn(-diff);
} else {
waveform().TrimOut(-diff);
}
} else {
if (mode == Timeline::kTrimIn) {
waveform().PrependSilence(diff);
} else {
waveform().AppendSilence(diff);
}
}
}
void ClipBlock::InvalidateCache(const TimeRange &range, NodeInput *from, NodeInput *source)
{
// If signal is from texture input, transform all times from media time to sequence time
+5
View File
@@ -72,6 +72,11 @@ public:
signals:
void PreviewUpdated();
protected:
virtual void LengthChangedEvent(const rational& old_length,
const rational& new_length,
const Timeline::MovementMode& mode) override;
private:
NodeInput* texture_input_;
+26 -62
View File
@@ -210,6 +210,10 @@ void TrackRippleRemoveAreaCommand::redo_internal()
// Split the block here
trim_in_ = static_cast<Block*>(trim_out_->copy());
if (trim_out_->type() == Block::kClip) {
static_cast<ClipBlock*>(trim_in_)->set_waveform(static_cast<ClipBlock*>(trim_out_)->waveform());
}
static_cast<NodeGraph*>(track_->parent())->AddNode(trim_in_);
Node::CopyInputs(trim_out_, trim_in_);
@@ -293,9 +297,15 @@ void TrackRippleRemoveAreaCommand::undo_internal()
// trim_in_ is our copy and trim_out_ is our original
track_->RippleRemoveBlock(trim_in_);
delete TakeNodeFromParentGraph(trim_in_);
trim_out_->set_length_and_media_out(trim_out_old_length_);
if (trim_out_->type() == Block::kClip) {
static_cast<ClipBlock*>(trim_out_)->waveform().OverwriteSums(static_cast<ClipBlock*>(trim_in_)->waveform(),
out_ - trim_out_->in());
}
delete TakeNodeFromParentGraph(trim_in_);
} else {
// If we picked up a block to trim the out point of
@@ -438,10 +448,20 @@ void BlockSplitCommand::redo_internal()
rational new_part_length = block_->length() - (point_ - block_->in());
AudioVisualWaveform split_waveform;
if (block_->type() == Block::kClip) {
split_waveform = static_cast<ClipBlock*>(block_)->waveform().Mid(new_length_);
}
block_->set_length_and_media_out(new_length_);
new_block_->set_length_and_media_in(new_part_length);
if (block_->type() == Block::kClip) {
static_cast<ClipBlock*>(new_block_)->set_waveform(split_waveform);
}
track_->InsertBlockAfter(new_block_, block_);
foreach (NodeInput* transition, transitions_to_move_) {
@@ -449,10 +469,6 @@ void BlockSplitCommand::redo_internal()
NodeParam::ConnectEdge(new_block_->output(), transition);
}
if (block_->type() == Block::kClip) {
static_cast<ClipBlock*>(new_block_)->set_waveform(static_cast<ClipBlock*>(block_)->waveform().Cut(new_length_));
}
track_->UnblockInvalidateCache();
}
@@ -471,7 +487,8 @@ void BlockSplitCommand::undo_internal()
}
if (block_->type() == Block::kClip) {
static_cast<ClipBlock*>(block_)->waveform().Append(static_cast<ClipBlock*>(new_block_)->waveform());
static_cast<ClipBlock*>(block_)->waveform().OverwriteSums(static_cast<ClipBlock*>(new_block_)->waveform(),
new_length_);
}
track_->UnblockInvalidateCache();
@@ -1006,14 +1023,6 @@ void BlockTrimCommand::redo_internal()
}
}
if (block_->type() == Block::kClip) {
if (mode_ == Timeline::kTrimIn) {
static_cast<ClipBlock*>(block_)->waveform().TrimIn(trim_diff);
} else {
static_cast<ClipBlock*>(block_)->waveform().TrimOut(trim_diff);
}
}
} else {
if (adjacent_) {
// If trimming LONGER, we'll need to trim the adjacent
@@ -1024,14 +1033,6 @@ void BlockTrimCommand::redo_internal()
adjacent_->set_length_and_media_in(adjacent_->length() + trim_diff);
}
}
if (block_->type() == Block::kClip) {
if (mode_ == Timeline::kTrimIn) {
static_cast<ClipBlock*>(block_)->waveform().PrependSilence(-trim_diff);
} else {
static_cast<ClipBlock*>(block_)->waveform().AppendSilence(-trim_diff);
}
}
}
track_->UnblockInvalidateCache();
@@ -1051,22 +1052,13 @@ void BlockTrimCommand::undo_internal()
if (we_created_adjacent_) {
// If we created a gap, just remove it straight up
track_->RippleRemoveBlock(adjacent_);
TakeNodeFromParentGraph(adjacent_);
delete adjacent_;
delete TakeNodeFromParentGraph(adjacent_);
adjacent_ = nullptr;
we_created_adjacent_ = false;
} else if (adjacent_) {
// If we adjusted an existing gap, unadjust here
adjacent_->set_length_and_media_out(adjacent_->length() - trim_diff);
}
if (block_->type() == Block::kClip) {
if (mode_ == Timeline::kTrimIn) {
static_cast<ClipBlock*>(block_)->waveform().PrependSilence(trim_diff);
} else {
static_cast<ClipBlock*>(block_)->waveform().AppendSilence(trim_diff);
}
}
} else {
if (adjacent_) {
// If trimmed LONGER, we adjusted an existing block
@@ -1075,14 +1067,6 @@ void BlockTrimCommand::undo_internal()
adjacent_->set_length_and_media_out(adjacent_->length() - trim_diff);
}
}
if (block_->type() == Block::kClip) {
if (mode_ == Timeline::kTrimIn) {
static_cast<ClipBlock*>(block_)->waveform().TrimIn(-trim_diff);
} else {
static_cast<ClipBlock*>(block_)->waveform().TrimOut(-trim_diff);
}
}
}
TimeRange invalidate_range;
@@ -1194,8 +1178,7 @@ void TrackReplaceBlockWithGapCommand::undo_internal()
if (we_created_gap_) {
// We made this gap, simply swap our gap back
track_->ReplaceBlock(gap_, block_);
TakeNodeFromParentGraph(gap_);
delete gap_;
delete TakeNodeFromParentGraph(gap_);
gap_ = nullptr;
} else {
// We must have extended an existing gap
@@ -1278,24 +1261,6 @@ void TrackSlideCommand::slide_internal(bool undo)
if (info.mode == Timeline::kTrimIn || info.mode == Timeline::kTrimOut) {
rational new_len = undo ? info.old_time : info.new_time;
if (info.block->type() == Block::kClip) {
AudioVisualWaveform& waveform = static_cast<ClipBlock*>(info.block)->waveform();
if (new_len < info.block->length()) {
if (info.mode == Timeline::kTrimIn) {
waveform.TrimIn(info.block->length() - new_len);
} else {
waveform.TrimOut(info.block->length() - new_len);
}
} else {
if (info.mode == Timeline::kTrimIn) {
waveform.PrependSilence(new_len - info.block->length());
} else {
waveform.AppendSilence(new_len - info.block->length());
}
}
}
if (info.mode == Timeline::kTrimIn) {
info.block->set_length_and_media_in(new_len);
} else {
@@ -1322,8 +1287,7 @@ void TrackSlideCommand::slide_internal(bool undo)
track->BlockInvalidateCache();
track->RippleRemoveBlock(gap);
TakeNodeFromParentGraph(gap);
delete gap;
delete TakeNodeFromParentGraph(gap);
track->UnblockInvalidateCache();
}