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_at_frame(void *handle, int frame, float pitch, char animated);
void BKE_sound_set_scene_sound_pitch_constant_range(void *handle,
int frame_start,
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);
}
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,
int frame_start,
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);
}
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)
@ -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;
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);
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;
int corrected_offset;
if (handle->flag == 1) {
if (seq_retiming_handle_is_transition_type(handle)) {
handle_start = handle;
handle_end = handle + 1;
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 = 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);
}
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)
{
if ((handle->flag & 1) != 0) {
if (!seq_retiming_handle_is_transition_type(handle)) {
seq_retiming_remove_gradient(scene, seq, handle);
return;
}
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);
return;
}
@ -433,7 +434,8 @@ SeqRetimingHandle *SEQ_retiming_add_gradient(const Scene *scene,
const int offset)
{
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;
}
@ -473,6 +475,13 @@ class RetimingRange {
int start, end;
float speed;
enum eRangeType {
LINEAR,
TRANSITION,
};
eRangeType type;
enum eIntersectType {
FULL,
PARTIAL_START,
@ -481,9 +490,10 @@ class RetimingRange {
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)
{
type = is_transition ? TRANSITION : LINEAR;
}
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_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);
}
}
@ -528,7 +539,11 @@ class RetimingRangeData {
{
if (ranges.is_empty()) {
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);
}
return *this;
@ -545,19 +560,21 @@ class RetimingRangeData {
}
else if (range.intersect_type(rhs_range) == range.PARTIAL_START) {
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;
ranges.insert(i, range_left);
}
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;
ranges.insert(i, range_left);
}
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(
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;
ranges.insert(i, range_left);
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)
{
RetimingRangeData retiming_data = seq_retiming_range_data_get(scene, seq);
for (const RetimingRange &range : retiming_data.ranges) {
BKE_sound_set_scene_sound_pitch_constant_range(
seq->scene_sound, range.start, range.end, range.speed);
for (int i = 0; i < retiming_data.ranges.size(); i++) {
RetimingRange range = retiming_data.ranges[i];
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);
}
}
}