implemented foundational reversed block code

Ensured renderers can handle clips that are reversed.
This commit is contained in:
itsmattkc
2019-12-24 16:17:33 +11:00
parent f0cd480540
commit 62f9e55609
5 changed files with 83 additions and 5 deletions
+41 -4
View File
@@ -33,6 +33,7 @@ SpeedDurationDialog::SpeedDurationDialog(const rational& timebase, const QList<C
// show them all as having the same parameters
bool same_speed = true;
bool same_duration = true;
bool all_reversed = true;
for (int i=1;i<clips.size();i++) {
ClipBlock* prev_clip = clips_.at(i-1);
@@ -50,8 +51,16 @@ SpeedDurationDialog::SpeedDurationDialog(const rational& timebase, const QList<C
same_duration = false;
}
// Check if all are reversed
if (all_reversed
&& prev_clip->is_reversed() != this_clip->is_reversed()) {
all_reversed = false;
}
// If we've already determined both are different, no need to continue
if (!same_speed && !same_duration) {
if (!same_speed
&& !same_duration
&& !all_reversed) {
break;
}
}
@@ -97,10 +106,15 @@ SpeedDurationDialog::SpeedDurationDialog(const rational& timebase, const QList<C
// Pick up when the speed or duration slider changes so we can programmatically link them
connect(speed_slider_, SIGNAL(ValueChanged(double)), this, SLOT(SpeedChanged()));
connect(duration_slider_, SIGNAL(ValueChanged(int64_t)), this, SLOT(DurationChanged()));
}
reverse_speed_checkbox_ = new QCheckBox(tr("Reverse Speed"));
layout->addWidget(reverse_speed_checkbox_);
reverse_speed_checkbox_ = new QCheckBox(tr("Reverse Speed"));
if (all_reversed) {
reverse_speed_checkbox_->setChecked(clips_.first()->is_reversed());
} else {
reverse_speed_checkbox_->setTristate();
}
layout->addWidget(reverse_speed_checkbox_);
}
maintain_audio_pitch_checkbox_ = new QCheckBox(tr("Maintain Audio Pitch"));
layout->addWidget(maintain_audio_pitch_checkbox_);
@@ -216,6 +230,10 @@ void SpeedDurationDialog::accept()
// Change the speed by calculating the appropriate media out point for this clip
new BlockSetMediaOutCommand(clip, new_media_out, command);
}
if (!reverse_speed_checkbox_->isTristate() && clip->is_reversed() != reverse_speed_checkbox_->isChecked()) {
new BlockReverseCommand(clip, command);
}
}
olive::undo_stack.pushIfHasChildren(command);
@@ -311,3 +329,22 @@ void SpeedDurationDialog::DurationChanged()
}
}
}
BlockReverseCommand::BlockReverseCommand(Block *block, QUndoCommand *parent) :
QUndoCommand(parent),
block_(block)
{
}
void BlockReverseCommand::redo()
{
rational temp = block_->media_in();
block_->set_media_in(block_->media_out());
block_->set_media_out(temp);
}
void BlockReverseCommand::undo()
{
// Since it's a simple swap, we can just run redo() again
redo();
}
+11
View File
@@ -44,4 +44,15 @@ private slots:
void DurationChanged();
};
class BlockReverseCommand : public QUndoCommand {
public:
BlockReverseCommand(Block* block, QUndoCommand* parent = nullptr);
virtual void redo() override;
virtual void undo() override;
private:
Block* block_;
};
#endif // SPEEDDURATIONDIALOG_H
+11 -1
View File
@@ -178,7 +178,17 @@ rational Block::media_length() const
double Block::speed() const
{
return media_length().toDouble() / length().toDouble();
return qAbs(media_length().toDouble() / length().toDouble());
}
bool Block::is_still() const
{
return (media_in() == media_out());
}
bool Block::is_reversed() const
{
return (media_out() < media_in());
}
const QString &Block::block_name() const
+2
View File
@@ -73,6 +73,8 @@ public:
rational media_length() const;
double speed() const;
bool is_still() const;
bool is_reversed() const;
const QString& block_name() const;
void set_block_name(const QString& name);
+18
View File
@@ -70,6 +70,24 @@ NodeValueTable AudioRenderWorker::RenderBlock(const TrackOutput *track, const Ti
samples_from_this_block = speed_adjusted_samples;
}
if (b->is_reversed()) {
int sample_size = audio_params_.samples_to_bytes(1);
int half_buffer_sz = samples_from_this_block.size() / 2;
char* temp_buffer = new char[sample_size];
for (int src_index=0;src_index<half_buffer_sz;src_index+=sample_size) {
char* src_ptr = samples_from_this_block.data() + src_index;
char* dst_ptr = samples_from_this_block.data() + samples_from_this_block.size() - sample_size - src_index;
// Simple swap
memcpy(temp_buffer, src_ptr, sample_size);
memcpy(src_ptr, dst_ptr, sample_size);
memcpy(dst_ptr, temp_buffer, sample_size);
}
delete [] temp_buffer;
}
copied_size = samples_from_this_block.size();
memcpy(block_range_buffer.data()+destination_offset,