VSE: Smooth transition for retiming tool #107197

Merged
Richard Antalik merged 20 commits from iss/blender:retiming-gradual into main 2023-05-16 22:33:19 +02:00
3 changed files with 63 additions and 18 deletions
Showing only changes of commit ee11e688bd - Show all commits

View File

@ -154,6 +154,8 @@ void BKE_sound_set_scene_sound_volume(void *handle, float volume, char animated)
void BKE_sound_set_scene_sound_pitch(void *handle, float pitch, char animated); void BKE_sound_set_scene_sound_pitch(void *handle, float pitch, char animated);
void BKE_sound_set_scene_sound_pitch_at_frame(void *handle, int frame, float pitch, char animated);
void BKE_sound_set_scene_sound_pitch_constant_range(void *handle, void BKE_sound_set_scene_sound_pitch_constant_range(void *handle,
int frame_start, int frame_start,
int frame_end, int frame_end,

View File

@ -819,6 +819,11 @@ void BKE_sound_set_scene_sound_pitch(void *handle, float pitch, char animated)
AUD_SequenceEntry_setAnimationData(handle, AUD_AP_PITCH, sound_cfra, &pitch, animated); AUD_SequenceEntry_setAnimationData(handle, AUD_AP_PITCH, sound_cfra, &pitch, animated);
} }
void BKE_sound_set_scene_sound_pitch_at_frame(void *handle, int frame, float pitch, char animated)
{
AUD_SequenceEntry_setAnimationData(handle, AUD_AP_PITCH, frame, &pitch, animated);
}
void BKE_sound_set_scene_sound_pitch_constant_range(void *handle, void BKE_sound_set_scene_sound_pitch_constant_range(void *handle,
int frame_start, int frame_start,
int frame_end, int frame_end,

View File

@ -206,9 +206,9 @@ static void seq_retiming_line_segments_tangent_circle(const SeqRetimingHandle *s
*radius = len_v2v2_db(p1_2, r_center); *radius = len_v2v2_db(p1_2, r_center);
} }
static void seq_retiming_evalualte_eased_segment() static bool seq_retiming_handle_is_transition_type(const SeqRetimingHandle *handle)
{ {
// return (handle->flag & 1) != 0;
} }
float seq_retiming_evaluate(const Sequence *seq, const int frame_index) float seq_retiming_evaluate(const Sequence *seq, const int frame_index)
@ -220,7 +220,7 @@ float seq_retiming_evaluate(const Sequence *seq, const int frame_index)
const int segment_frame_index = frame_index - start_handle->strip_frame_index; const int segment_frame_index = frame_index - start_handle->strip_frame_index;
if (start_handle->flag != 1) { if (!seq_retiming_handle_is_transition_type(start_handle)) {
const float segment_step = seq_retiming_segment_step_get(start_handle); const float segment_step = seq_retiming_segment_step_get(start_handle);
return start_handle->retiming_factor + segment_step * segment_frame_index; return start_handle->retiming_factor + segment_step * segment_frame_index;
} }
@ -300,7 +300,7 @@ static void seq_retiming_offset_gradient_handle(const Scene *scene,
SeqRetimingHandle *handle_start, *handle_end; SeqRetimingHandle *handle_start, *handle_end;
int corrected_offset; int corrected_offset;
if (handle->flag == 1) { if (seq_retiming_handle_is_transition_type(handle)) {
handle_start = handle; handle_start = handle;
handle_end = handle + 1; handle_end = handle + 1;
corrected_offset = offset; corrected_offset = offset;
@ -357,7 +357,8 @@ void SEQ_retiming_offset_handle(const Scene *scene,
corrected_offset = max_ii(corrected_offset, offset_min); corrected_offset = max_ii(corrected_offset, offset_min);
corrected_offset = min_ii(corrected_offset, offset_max); corrected_offset = min_ii(corrected_offset, offset_max);
if (handle->flag == 1 || prev_handle->flag == 1) { if (seq_retiming_handle_is_transition_type(handle) ||
seq_retiming_handle_is_transition_type(prev_handle)) {
seq_retiming_offset_gradient_handle(scene, seq, handle, corrected_offset); seq_retiming_offset_gradient_handle(scene, seq, handle, corrected_offset);
} }
else { else {
@ -415,12 +416,12 @@ static void seq_retiming_remove_gradient(const Scene *scene,
void SEQ_retiming_remove_handle(const Scene *scene, Sequence *seq, SeqRetimingHandle *handle) void SEQ_retiming_remove_handle(const Scene *scene, Sequence *seq, SeqRetimingHandle *handle)
{ {
if ((handle->flag & 1) != 0) { if (!seq_retiming_handle_is_transition_type(handle)) {
seq_retiming_remove_gradient(scene, seq, handle); seq_retiming_remove_gradient(scene, seq, handle);
return; return;
} }
SeqRetimingHandle *previous_handle = handle - 1; SeqRetimingHandle *previous_handle = handle - 1;
if ((previous_handle->flag & 1) != 0) { if (!seq_retiming_handle_is_transition_type(previous_handle)) {
seq_retiming_remove_gradient(scene, seq, previous_handle); seq_retiming_remove_gradient(scene, seq, previous_handle);
return; return;
} }
@ -433,7 +434,8 @@ SeqRetimingHandle *SEQ_retiming_add_gradient(const Scene *scene,
const int offset) const int offset)
{ {
SeqRetimingHandle *prev_handle = handle - 1; SeqRetimingHandle *prev_handle = handle - 1;
if (handle->flag == 1 || prev_handle->flag == 1) { if (seq_retiming_handle_is_transition_type(handle) ||
seq_retiming_handle_is_transition_type(prev_handle)) {
return nullptr; return nullptr;
} }
@ -473,6 +475,13 @@ class RetimingRange {
int start, end; int start, end;
float speed; float speed;
enum eRangeType {
LINEAR,
TRANSITION,
};
eRangeType type;
enum eIntersectType { enum eIntersectType {
FULL, FULL,
PARTIAL_START, PARTIAL_START,
@ -481,9 +490,10 @@ class RetimingRange {
NONE, NONE,
}; };
RetimingRange(int start_frame, int end_frame, float speed) RetimingRange(int start_frame, int end_frame, float speed, bool is_transition)
: start(start_frame), end(end_frame), speed(speed) : start(start_frame), end(end_frame), speed(speed)
{ {
type = is_transition ? TRANSITION : LINEAR;
} }
const eIntersectType intersect_type(const RetimingRange &other) const const eIntersectType intersect_type(const RetimingRange &other) const
@ -519,7 +529,8 @@ class RetimingRangeData {
int frame_start = SEQ_time_start_frame_get(seq) + handle_prev->strip_frame_index; int frame_start = SEQ_time_start_frame_get(seq) + handle_prev->strip_frame_index;
int frame_end = SEQ_time_start_frame_get(seq) + handle.strip_frame_index; int frame_end = SEQ_time_start_frame_get(seq) + handle.strip_frame_index;
RetimingRange range = RetimingRange(frame_start, frame_end, speed); RetimingRange range = RetimingRange(
frame_start, frame_end, speed, seq_retiming_handle_is_transition_type(handle_prev));
ranges.append(range); ranges.append(range);
} }
} }
@ -528,7 +539,11 @@ class RetimingRangeData {
{ {
if (ranges.is_empty()) { if (ranges.is_empty()) {
for (const RetimingRange &rhs_range : rhs.ranges) { for (const RetimingRange &rhs_range : rhs.ranges) {
RetimingRange range = RetimingRange(rhs_range.start, rhs_range.end, rhs_range.speed); RetimingRange range = RetimingRange(
rhs_range.start,
rhs_range.end,
rhs_range.speed,
false); // xxx hardcoded, make this model nicer somehow...
ranges.append(range); ranges.append(range);
} }
return *this; return *this;
@ -545,19 +560,21 @@ class RetimingRangeData {
} }
else if (range.intersect_type(rhs_range) == range.PARTIAL_START) { else if (range.intersect_type(rhs_range) == range.PARTIAL_START) {
RetimingRange range_left = RetimingRange( RetimingRange range_left = RetimingRange(
range.start, rhs_range.end, range.speed * rhs_range.speed); range.start, rhs_range.end, range.speed * rhs_range.speed, false);
range.start = rhs_range.end + 1; range.start = rhs_range.end + 1;
ranges.insert(i, range_left); ranges.insert(i, range_left);
} }
else if (range.intersect_type(rhs_range) == range.PARTIAL_END) { else if (range.intersect_type(rhs_range) == range.PARTIAL_END) {
RetimingRange range_left = RetimingRange(range.start, rhs_range.start - 1, range.speed); RetimingRange range_left = RetimingRange(
range.start, rhs_range.start - 1, range.speed, false);
range.start = rhs_range.start; range.start = rhs_range.start;
ranges.insert(i, range_left); ranges.insert(i, range_left);
} }
else if (range.intersect_type(rhs_range) == range.INSIDE) { else if (range.intersect_type(rhs_range) == range.INSIDE) {
RetimingRange range_left = RetimingRange(range.start, rhs_range.start - 1, range.speed); RetimingRange range_left = RetimingRange(
range.start, rhs_range.start - 1, range.speed, false);
RetimingRange range_mid = RetimingRange( RetimingRange range_mid = RetimingRange(
rhs_range.start, rhs_range.start, rhs_range.speed * range.speed); rhs_range.start, rhs_range.start, rhs_range.speed * range.speed, false);
range.start = rhs_range.end + 1; range.start = rhs_range.end + 1;
ranges.insert(i, range_left); ranges.insert(i, range_left);
ranges.insert(i, range_mid); ranges.insert(i, range_mid);
@ -586,9 +603,30 @@ static RetimingRangeData seq_retiming_range_data_get(const Scene *scene, const S
void SEQ_retiming_sound_animation_data_set(const Scene *scene, const Sequence *seq) void SEQ_retiming_sound_animation_data_set(const Scene *scene, const Sequence *seq)
{ {
RetimingRangeData retiming_data = seq_retiming_range_data_get(scene, seq); RetimingRangeData retiming_data = seq_retiming_range_data_get(scene, seq);
for (const RetimingRange &range : retiming_data.ranges) { for (int i = 0; i < retiming_data.ranges.size(); i++) {
BKE_sound_set_scene_sound_pitch_constant_range( RetimingRange range = retiming_data.ranges[i];
seq->scene_sound, range.start, range.end, range.speed); if (range.type == range.TRANSITION) {
RetimingRange previous = retiming_data.ranges[i - 1];
RetimingRange next = retiming_data.ranges[i + 1];
int range_start = range.start;
float speed_prev = previous.speed;
float speed_next = next.speed;
int range_length = range.end - range.start - 1;
float speed_diff = speed_next - speed_prev;
for (int j = 0; j < range_length; j++) {
int frame = range_start + j;
float fac = j / static_cast<float>(range_length);
float speed_at_frame = speed_prev + fac * speed_diff;
BKE_sound_set_scene_sound_pitch_at_frame(seq->scene_sound, frame, speed_at_frame, true);
}
}
else {
BKE_sound_set_scene_sound_pitch_constant_range(
seq->scene_sound, range.start, range.end, range.speed);
}
} }
} }