Improved Keyframe Performance (#197)

* Refactor of Coorindate and Keyframe optimized for performance (much faster than previously). Also refactored FrameMapper to not use a Keyframe, and to only process frame mapping when needed... speeding up Json loading of project files.

* Fixing FrameMapper linear calculation to match existing Keyframe calculation

* Fixing Keyframe to pass original unit tests, and correctly calculate the Keyframe repeat fractions and deltas.

* Small refactor of time mapped logic in Clip.cpp
This commit is contained in:
Jonathan Thomas
2019-03-06 15:35:03 -06:00
committed by GitHub
parent 728e0022a2
commit 8f385c112a
7 changed files with 166 additions and 171 deletions

View File

@@ -296,17 +296,48 @@ bool Keyframe::IsIncreasing(int index)
Process();
// Is index a valid point?
if (index >= 0 && index < Values.size())
// Return value
return long(round(Values[index].IsIncreasing()));
else if (index < 0 && Values.size() > 0)
// Return the minimum value
return long(round(Values[0].IsIncreasing()));
else if (index >= Values.size() && Values.size() > 0)
// return the maximum value
return long(round(Values[Values.size() - 1].IsIncreasing()));
if (index >= 1 && (index + 1) < Values.size()) {
int64_t current_value = GetLong(index);
int64_t previous_value = 0;
int64_t next_value = 0;
int64_t previous_repeats = 0;
int64_t next_repeats = 0;
// Loop backwards and look for the next unique value
for (vector<Coordinate>::iterator backwards_it = Values.begin() + index; backwards_it != Values.begin(); backwards_it--) {
previous_value = long(round((*backwards_it).Y));
if (previous_value == current_value) {
// Found same value
previous_repeats++;
} else {
// Found non repeating value, no more repeats found
break;
}
}
// Loop forwards and look for the next unique value
for (vector<Coordinate>::iterator forwards_it = Values.begin() + (index + 1); forwards_it != Values.end(); forwards_it++) {
next_value = long(round((*forwards_it).Y));
if (next_value == current_value) {
// Found same value
next_repeats++;
} else {
// Found non repeating value, no more repeats found
break;
}
}
if (current_value < next_value) {
// Increasing
return true;
}
else if (current_value >= next_value) {
// Decreasing
return false;
}
}
else
// return the default direction of most curves (i.e. increasing is true)
// return default true (since most curves increase)
return true;
}
@@ -385,6 +416,7 @@ void Keyframe::SetJsonValue(Json::Value root) {
}
// Get the fraction that represents how many times this value is repeated in the curve
// This is depreciated and will be removed soon.
Fraction Keyframe::GetRepeatFraction(int64_t index)
{
// Check if it needs to be processed
@@ -392,17 +424,42 @@ Fraction Keyframe::GetRepeatFraction(int64_t index)
Process();
// Is index a valid point?
if (index >= 0 && index < Values.size())
// Return value
return Values[index].Repeat();
else if (index < 0 && Values.size() > 0)
// Return the minimum value
return Values[0].Repeat();
else if (index >= Values.size() && Values.size() > 0)
// return the maximum value
return Values[Values.size() - 1].Repeat();
if (index >= 1 && (index + 1) < Values.size()) {
int64_t current_value = GetLong(index);
int64_t previous_value = 0;
int64_t next_value = 0;
int64_t previous_repeats = 0;
int64_t next_repeats = 0;
// Loop backwards and look for the next unique value
for (vector<Coordinate>::iterator backwards_it = Values.begin() + index; backwards_it != Values.begin(); backwards_it--) {
previous_value = long(round((*backwards_it).Y));
if (previous_value == current_value) {
// Found same value
previous_repeats++;
} else {
// Found non repeating value, no more repeats found
break;
}
}
// Loop forwards and look for the next unique value
for (vector<Coordinate>::iterator forwards_it = Values.begin() + (index + 1); forwards_it != Values.end(); forwards_it++) {
next_value = long(round((*forwards_it).Y));
if (next_value == current_value) {
// Found same value
next_repeats++;
} else {
// Found non repeating value, no more repeats found
break;
}
}
int64_t total_repeats = previous_repeats + next_repeats;
return Fraction(previous_repeats, total_repeats);
}
else
// return a blank coordinate (0,0)
// return a blank coordinate
return Fraction(1,1);
}
@@ -414,17 +471,48 @@ double Keyframe::GetDelta(int64_t index)
Process();
// Is index a valid point?
if (index >= 0 && index < Values.size())
// Return value
return Values[index].Delta();
else if (index < 0 && Values.size() > 0)
// Return the minimum value
return Values[0].Delta();
else if (index >= Values.size() && Values.size() > 0)
// return the maximum value
return Values[Values.size() - 1].Delta();
if (index >= 1 && (index + 1) < Values.size()) {
int64_t current_value = GetLong(index);
int64_t previous_value = 0;
int64_t next_value = 0;
int64_t previous_repeats = 0;
int64_t next_repeats = 0;
// Loop backwards and look for the next unique value
for (vector<Coordinate>::iterator backwards_it = Values.begin() + index; backwards_it != Values.begin(); backwards_it--) {
previous_value = long(round((*backwards_it).Y));
if (previous_value == current_value) {
// Found same value
previous_repeats++;
} else {
// Found non repeating value, no more repeats found
break;
}
}
// Loop forwards and look for the next unique value
for (vector<Coordinate>::iterator forwards_it = Values.begin() + (index + 1); forwards_it != Values.end(); forwards_it++) {
next_value = long(round((*forwards_it).Y));
if (next_value == current_value) {
// Found same value
next_repeats++;
} else {
// Found non repeating value, no more repeats found
break;
}
}
// Check for matching previous value (special case for 1st element)
if (current_value == previous_value)
previous_value = 0;
if (previous_repeats == 1)
return current_value - previous_value;
else
return 0.0;
}
else
// return a blank coordinate (0,0)
// return a blank coordinate
return 0.0;
}
@@ -529,7 +617,7 @@ void Keyframe::PrintValues() {
for (vector<Coordinate>::iterator it = Values.begin() + 1; it != Values.end(); it++) {
Coordinate c = *it;
cout << long(round(c.X)) << "\t" << c.Y << "\t" << c.IsIncreasing() << "\t" << c.Repeat().num << "\t" << c.Repeat().den << "\t" << c.Delta() << endl;
cout << long(round(c.X)) << "\t" << c.Y << "\t" << IsIncreasing(c.X) << "\t" << GetRepeatFraction(c.X).num << "\t" << GetRepeatFraction(c.X).den << "\t" << GetDelta(c.X) << endl;
}
}
@@ -567,69 +655,6 @@ void Keyframe::Process() {
// process segment p1,p2
ProcessSegment(x, p1, p2);
}
// Loop through each Value, and set the direction of the coordinate. This is used
// when time mapping, to determine what direction the audio waveforms play.
bool increasing = true;
int repeat_count = 1;
int64_t last_value = 0;
for (vector<Coordinate>::iterator it = Values.begin() + 1; it != Values.end(); it++) {
int current_value = long(round((*it).Y));
int64_t next_value = long(round((*it).Y));
int64_t prev_value = long(round((*it).Y));
if (it + 1 != Values.end())
next_value = long(round((*(it + 1)).Y));
if (it - 1 >= Values.begin())
prev_value = long(round((*(it - 1)).Y));
// Loop forward and look for the next unique value (to determine direction)
for (vector<Coordinate>::iterator direction_it = it + 1; direction_it != Values.end(); direction_it++) {
int64_t next = long(round((*direction_it).Y));
// Detect direction
if (current_value < next)
{
increasing = true;
break;
}
else if (current_value > next)
{
increasing = false;
break;
}
}
// Set direction
(*it).IsIncreasing(increasing);
// Detect repeated Y value
if (current_value == last_value)
// repeated, so increment count
repeat_count++;
else
// reset repeat counter
repeat_count = 1;
// Detect how many 'more' times it's repeated
int additional_repeats = 0;
for (vector<Coordinate>::iterator repeat_it = it + 1; repeat_it != Values.end(); repeat_it++) {
int64_t next = long(round((*repeat_it).Y));
if (next == current_value)
// repeated, so increment count
additional_repeats++;
else
break; // stop looping
}
// Set repeat fraction
(*it).Repeat(Fraction(repeat_count, repeat_count + additional_repeats));
// Set delta (i.e. different from previous unique Y value)
(*it).Delta(current_value - last_value);
// track the last value
last_value = current_value;
}
}
// reset flag