Commit aa260864 authored by Raymond Toy's avatar Raymond Toy Committed by Commit Bot

Handle AudioParam start clamping more efficiently.

Add a new vector to keep track of all newly inserted events.  This
vector is processed once in the audio thread to clamp the start time
of the event if needed.  Once processed, this vector is cleared.

Previously, the clamp check would process the entire event list to see
if any event needed to be clamped.  Most of the time, this is wasted
because there are no events to be clamped because they're all in the
future or because they've already been clamped.

Also removed unneeded member functions and variables.

Bug: 780125
Test: 
Change-Id: I73b871d8fa87a68e482cb98d48af33e05d1f0cfb
Reviewed-on: https://chromium-review.googlesource.com/747071Reviewed-by: default avatarHongchan Choi <hongchan@chromium.org>
Commit-Queue: Raymond Toy <rtoy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#516336}
parent ef157deb
...@@ -293,7 +293,6 @@ AudioParamTimeline::ParamEvent::ParamEvent( ...@@ -293,7 +293,6 @@ AudioParamTimeline::ParamEvent::ParamEvent(
curve_points_per_second_(curve_points_per_second), curve_points_per_second_(curve_points_per_second),
curve_end_value_(curve_end_value), curve_end_value_(curve_end_value),
saved_event_(std::move(saved_event)), saved_event_(std::move(saved_event)),
needs_time_clamp_check_(true),
has_default_cancelled_value_(false) { has_default_cancelled_value_(false) {
curve_ = curve; curve_ = curve;
} }
...@@ -312,7 +311,6 @@ AudioParamTimeline::ParamEvent::ParamEvent(ParamEvent::Type type, ...@@ -312,7 +311,6 @@ AudioParamTimeline::ParamEvent::ParamEvent(ParamEvent::Type type,
curve_points_per_second_(0), curve_points_per_second_(0),
curve_end_value_(0), curve_end_value_(0),
saved_event_(nullptr), saved_event_(nullptr),
needs_time_clamp_check_(true),
has_default_cancelled_value_(false) { has_default_cancelled_value_(false) {
DCHECK_EQ(type, ParamEvent::kSetValue); DCHECK_EQ(type, ParamEvent::kSetValue);
} }
...@@ -335,7 +333,6 @@ AudioParamTimeline::ParamEvent::ParamEvent(ParamEvent::Type type, ...@@ -335,7 +333,6 @@ AudioParamTimeline::ParamEvent::ParamEvent(ParamEvent::Type type,
curve_points_per_second_(0), curve_points_per_second_(0),
curve_end_value_(0), curve_end_value_(0),
saved_event_(nullptr), saved_event_(nullptr),
needs_time_clamp_check_(true),
has_default_cancelled_value_(false) { has_default_cancelled_value_(false) {
DCHECK(type == ParamEvent::kLinearRampToValue || DCHECK(type == ParamEvent::kLinearRampToValue ||
type == ParamEvent::kExponentialRampToValue); type == ParamEvent::kExponentialRampToValue);
...@@ -356,7 +353,6 @@ AudioParamTimeline::ParamEvent::ParamEvent(ParamEvent::Type type, ...@@ -356,7 +353,6 @@ AudioParamTimeline::ParamEvent::ParamEvent(ParamEvent::Type type,
curve_points_per_second_(0), curve_points_per_second_(0),
curve_end_value_(0), curve_end_value_(0),
saved_event_(nullptr), saved_event_(nullptr),
needs_time_clamp_check_(true),
has_default_cancelled_value_(false) { has_default_cancelled_value_(false) {
DCHECK_EQ(type, ParamEvent::kSetTarget); DCHECK_EQ(type, ParamEvent::kSetTarget);
} }
...@@ -378,7 +374,6 @@ AudioParamTimeline::ParamEvent::ParamEvent(ParamEvent::Type type, ...@@ -378,7 +374,6 @@ AudioParamTimeline::ParamEvent::ParamEvent(ParamEvent::Type type,
curve_points_per_second_(curve_points_per_second), curve_points_per_second_(curve_points_per_second),
curve_end_value_(curve_end_value), curve_end_value_(curve_end_value),
saved_event_(nullptr), saved_event_(nullptr),
needs_time_clamp_check_(true),
has_default_cancelled_value_(false) { has_default_cancelled_value_(false) {
DCHECK_EQ(type, ParamEvent::kSetValueCurve); DCHECK_EQ(type, ParamEvent::kSetValueCurve);
unsigned curve_length = curve.size(); unsigned curve_length = curve.size();
...@@ -401,7 +396,6 @@ AudioParamTimeline::ParamEvent::ParamEvent( ...@@ -401,7 +396,6 @@ AudioParamTimeline::ParamEvent::ParamEvent(
curve_points_per_second_(0), curve_points_per_second_(0),
curve_end_value_(0), curve_end_value_(0),
saved_event_(std::move(saved_event)), saved_event_(std::move(saved_event)),
needs_time_clamp_check_(true),
has_default_cancelled_value_(false) { has_default_cancelled_value_(false) {
DCHECK_EQ(type, ParamEvent::kCancelValues); DCHECK_EQ(type, ParamEvent::kCancelValues);
} }
...@@ -572,6 +566,7 @@ void AudioParamTimeline::InsertEvent(std::unique_ptr<ParamEvent> event, ...@@ -572,6 +566,7 @@ void AudioParamTimeline::InsertEvent(std::unique_ptr<ParamEvent> event,
if (events_[i]->Time() == insert_time && if (events_[i]->Time() == insert_time &&
events_[i]->GetType() == event->GetType()) { events_[i]->GetType() == event->GetType()) {
events_[i] = std::move(event); events_[i] = std::move(event);
new_events_.insert(events_[i].get());
return; return;
} }
...@@ -580,6 +575,7 @@ void AudioParamTimeline::InsertEvent(std::unique_ptr<ParamEvent> event, ...@@ -580,6 +575,7 @@ void AudioParamTimeline::InsertEvent(std::unique_ptr<ParamEvent> event,
} }
events_.insert(i, std::move(event)); events_.insert(i, std::move(event));
new_events_.insert(events_[i].get());
} }
bool AudioParamTimeline::HasValues() const { bool AudioParamTimeline::HasValues() const {
...@@ -614,7 +610,7 @@ void AudioParamTimeline::CancelScheduledValues( ...@@ -614,7 +610,7 @@ void AudioParamTimeline::CancelScheduledValues(
// Remove all events starting at startTime. // Remove all events starting at startTime.
for (unsigned i = 0; i < events_.size(); ++i) { for (unsigned i = 0; i < events_.size(); ++i) {
if (events_[i]->Time() >= start_time) { if (events_[i]->Time() >= start_time) {
events_.EraseAt(i, events_.size() - i); RemoveCancelledEvents(i);
break; break;
} }
} }
...@@ -726,8 +722,7 @@ void AudioParamTimeline::CancelAndHoldAtTime(double cancel_time, ...@@ -726,8 +722,7 @@ void AudioParamTimeline::CancelAndHoldAtTime(double cancel_time,
// Now remove all the following events from the timeline. // Now remove all the following events from the timeline.
if (cancelled_event_index < events_.size()) { if (cancelled_event_index < events_.size()) {
events_.EraseAt(cancelled_event_index, RemoveCancelledEvents(cancelled_event_index);
events_.size() - cancelled_event_index);
} }
// Insert the new event, if any. // Insert the new event, if any.
...@@ -819,9 +814,12 @@ float AudioParamTimeline::ValuesForFrameRangeImpl(size_t start_frame, ...@@ -819,9 +814,12 @@ float AudioParamTimeline::ValuesForFrameRangeImpl(size_t start_frame,
int number_of_events = events_.size(); int number_of_events = events_.size();
if (new_events_.size() > 0) {
ClampNewEventsToCurrentTime(start_frame / sample_rate);
}
if (number_of_events > 0) { if (number_of_events > 0) {
double current_time = start_frame / sample_rate; double current_time = start_frame / sample_rate;
ClampToCurrentTime(number_of_events, start_frame, sample_rate);
if (HandleAllEventsInThePast(current_time, sample_rate, default_value, if (HandleAllEventsInThePast(current_time, sample_rate, default_value,
number_of_values, values)) number_of_values, values))
...@@ -986,8 +984,12 @@ float AudioParamTimeline::ValuesForFrameRangeImpl(size_t start_frame, ...@@ -986,8 +984,12 @@ float AudioParamTimeline::ValuesForFrameRangeImpl(size_t start_frame,
// remove them so we don't have to check them ever again. (This MUST be // remove them so we don't have to check them ever again. (This MUST be
// running with the m_events lock so we can safely modify the m_events // running with the m_events lock so we can safely modify the m_events
// array.) // array.)
if (last_skipped_event_index > 0) if (last_skipped_event_index > 0) {
// |new_events_| should be empty here so we don't have to
// do any updates due to this mutation of |events_|.
DCHECK_EQ(new_events_.size(), 0u);
events_.EraseAt(0, last_skipped_event_index - 1); events_.EraseAt(0, last_skipped_event_index - 1);
}
// If there's any time left after processing the last event then just // If there's any time left after processing the last event then just
// propagate the last value to the end of the values buffer. // propagate the last value to the end of the values buffer.
...@@ -1069,41 +1071,23 @@ bool AudioParamTimeline::IsEventCurrent(const ParamEvent* event, ...@@ -1069,41 +1071,23 @@ bool AudioParamTimeline::IsEventCurrent(const ParamEvent* event,
return true; return true;
} }
void AudioParamTimeline::ClampToCurrentTime(int number_of_events, void AudioParamTimeline::ClampNewEventsToCurrentTime(double current_time) {
size_t start_frame, bool clamped_some_event_time = false;
double sample_rate) {
if (number_of_events > 0) {
bool clamped_some_event_time = false;
double current_time = start_frame / sample_rate;
// Look at all the events in the timeline and check to see if any needs
// to clamp the start time to the current time.
for (int k = 0; k < number_of_events; ++k) {
ParamEvent* event = events_[k].get();
// We're examining the event for the first time and the event time is
// in the past so clamp the event time to the current time (start of
// the rendering quantum).
if (event->NeedsTimeClampCheck()) {
if (event->Time() < current_time) {
event->SetTime(current_time);
clamped_some_event_time = true;
}
// In all cases, we can clear the flag because the event is either for (auto event : new_events_) {
// in the future, or we've already checked it (just now). if (event->Time() < current_time) {
event->ClearTimeClampCheck(); event->SetTime(current_time);
} clamped_some_event_time = true;
} }
}
if (clamped_some_event_time) { if (clamped_some_event_time) {
// If we clamped some event time to current time, we need to // If we clamped some event time to current time, we need to sort
// sort the event list in time order again, but it must be // the event list in time order again, but it must be stable!
// stable! std::stable_sort(events_.begin(), events_.end(), ParamEvent::EventPreceeds);
std::stable_sort(events_.begin(), events_.end(),
ParamEvent::EventPreceeds);
}
} }
new_events_.clear();
} }
bool AudioParamTimeline::HandleAllEventsInThePast(double current_time, bool AudioParamTimeline::HandleAllEventsInThePast(double current_time,
...@@ -1193,7 +1177,6 @@ void AudioParamTimeline::ProcessSetTargetFollowedByRamp( ...@@ -1193,7 +1177,6 @@ void AudioParamTimeline::ProcessSetTargetFollowedByRamp(
// Clear the clamp check because this doesn't need it. // Clear the clamp check because this doesn't need it.
events_[event_index] = events_[event_index] =
ParamEvent::CreateSetValueEvent(value, current_frame / sample_rate); ParamEvent::CreateSetValueEvent(value, current_frame / sample_rate);
events_[event_index]->ClearTimeClampCheck();
// Update our pointer to the current event because we just changed it. // Update our pointer to the current event because we just changed it.
event = events_[event_index].get(); event = events_[event_index].get();
...@@ -1915,4 +1898,18 @@ void AudioParamTimeline::WarnSetterOverlapsEvent( ...@@ -1915,4 +1898,18 @@ void AudioParamTimeline::WarnSetterOverlapsEvent(
" overlaps event " + message)); " overlaps event " + message));
} }
void AudioParamTimeline::RemoveCancelledEvents(size_t first_event_to_remove) {
// For all the events that are being removed, also remove that event
// from |new_events_|.
if (new_events_.size() > 0) {
for (size_t k = first_event_to_remove; k < events_.size(); ++k) {
new_events_.erase(events_[k].get());
}
}
// Now we can remove the cancelled events from the list.
events_.EraseAt(first_event_to_remove,
events_.size() - first_event_to_remove);
}
} // namespace blink } // namespace blink
...@@ -173,8 +173,6 @@ class AudioParamTimeline { ...@@ -173,8 +173,6 @@ class AudioParamTimeline {
Vector<float>& Curve() { return curve_; } Vector<float>& Curve() { return curve_; }
float InitialValue() const { return initial_value_; } float InitialValue() const { return initial_value_; }
double CallTime() const { return call_time_; } double CallTime() const { return call_time_; }
bool NeedsTimeClampCheck() const { return needs_time_clamp_check_; }
void ClearTimeClampCheck() { needs_time_clamp_check_ = false; }
double CurvePointsPerSecond() const { return curve_points_per_second_; } double CurvePointsPerSecond() const { return curve_points_per_second_; }
float CurveEndValue() const { return curve_end_value_; } float CurveEndValue() const { return curve_end_value_; }
...@@ -265,10 +263,6 @@ class AudioParamTimeline { ...@@ -265,10 +263,6 @@ class AudioParamTimeline {
// scheduled cancel time. // scheduled cancel time.
std::unique_ptr<ParamEvent> saved_event_; std::unique_ptr<ParamEvent> saved_event_;
// True if the start time needs to be checked against current time
// to implement clamping.
bool needs_time_clamp_check_;
// True if a default value has been assigned to the CancelValues event. // True if a default value has been assigned to the CancelValues event.
bool has_default_cancelled_value_; bool has_default_cancelled_value_;
}; };
...@@ -358,10 +352,10 @@ class AudioParamTimeline { ...@@ -358,10 +352,10 @@ class AudioParamTimeline {
size_t current_frame, size_t current_frame,
double sample_rate) const; double sample_rate) const;
// Clamp event times to current time, if needed. // Clamp times to current time, if needed for any new events. Note,
void ClampToCurrentTime(int number_of_events, // this method can mutate |events_|, so do call this only in safe
size_t start_frame, // places.
double sample_rate); void ClampNewEventsToCurrentTime(double current_time);
// Handle the case where the last event in the timeline is in the // Handle the case where the last event in the timeline is in the
// past. Returns false if any event is not in the past. Otherwise, // past. Returns false if any event is not in the past. Otherwise,
...@@ -468,10 +462,22 @@ class AudioParamTimeline { ...@@ -468,10 +462,22 @@ class AudioParamTimeline {
size_t event_index, size_t event_index,
BaseAudioContext&) const; BaseAudioContext&) const;
// When cancelling events, remove the items from |events_| starting
// at the given index. Update |new_events_| too.
void RemoveCancelledEvents(size_t first_event_to_remove);
// Vector of all automation events for the AudioParam. Access must // Vector of all automation events for the AudioParam. Access must
// be locked via m_eventsLock. // be locked via m_eventsLock.
Vector<std::unique_ptr<ParamEvent>> events_; Vector<std::unique_ptr<ParamEvent>> events_;
// Vector of raw pointers to the actual ParamEvent that was
// inserted. As new events are added, |new_events_| is updated with
// tne new event. When the timline is processed, these events are
// clamped to current time by |ClampNewEventsToCurrentTime|. Access
// must be locked via |events_lock_|. Must be maintained together
// with |events_|.
HashSet<ParamEvent*> new_events_;
mutable Mutex events_lock_; mutable Mutex events_lock_;
// Smoothing (de-zippering) // Smoothing (de-zippering)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment