blob: 282549f81cd767091e27aa7d587b338a638fe352 [file] [log] [blame]
/*
* Copyright (C) 2011 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef AudioParamTimeline_h
#define AudioParamTimeline_h
#include "core/dom/DOMTypedArray.h"
#include "modules/webaudio/AudioDestinationNode.h"
#include "modules/webaudio/BaseAudioContext.h"
#include "platform/wtf/Forward.h"
#include "platform/wtf/Threading.h"
#include "platform/wtf/Vector.h"
#include <tuple>
namespace blink {
class AudioParamTimeline {
DISALLOW_NEW();
public:
AudioParamTimeline() {}
void SetValueAtTime(float value, double time, ExceptionState&);
void LinearRampToValueAtTime(float value,
double time,
float initial_value,
double call_time,
ExceptionState&);
void ExponentialRampToValueAtTime(float value,
double time,
float initial_value,
double call_time,
ExceptionState&);
void SetTargetAtTime(float target,
double time,
double time_constant,
ExceptionState&);
void SetValueCurveAtTime(const Vector<float>& curve,
double time,
double duration,
ExceptionState&);
void CancelScheduledValues(double start_time, ExceptionState&);
void CancelAndHoldAtTime(double cancel_time, ExceptionState&);
// hasValue is set to true if a valid timeline value is returned.
// otherwise defaultValue is returned.
float ValueForContextTime(AudioDestinationHandler&,
float default_value,
bool& has_value,
float min_value,
float max_value);
// Given the time range in frames, calculates parameter values into the values
// buffer and returns the last parameter value calculated for "values" or the
// defaultValue if none were calculated. controlRate is the rate (number per
// second) at which parameter values will be calculated. It should equal
// sampleRate for sample-accurate parameter changes, and otherwise will
// usually match the render quantum size such that the parameter value changes
// once per render quantum.
float ValuesForFrameRange(size_t start_frame,
size_t end_frame,
float default_value,
float* values,
unsigned number_of_values,
double sample_rate,
double control_rate,
float min_value,
float max_value);
// Returns true if this AudioParam has any events on it.
bool HasValues() const;
float SmoothedValue() { return smoothed_value_; }
void SetSmoothedValue(float v) { smoothed_value_ = v; }
private:
class ParamEvent {
public:
enum Type {
kSetValue,
kLinearRampToValue,
kExponentialRampToValue,
kSetTarget,
kSetValueCurve,
// For cancelValuesAndHold
kCancelValues,
kLastType
};
static std::unique_ptr<ParamEvent> CreateLinearRampEvent(
float value,
double time,
float initial_value,
double call_time);
static std::unique_ptr<ParamEvent> CreateExponentialRampEvent(
float value,
double time,
float initial_value,
double call_time);
static std::unique_ptr<ParamEvent> CreateSetValueEvent(float value,
double time);
static std::unique_ptr<ParamEvent>
CreateSetTargetEvent(float value, double time, double time_constant);
static std::unique_ptr<ParamEvent> CreateSetValueCurveEvent(
const Vector<float>& curve,
double time,
double duration);
static std::unique_ptr<ParamEvent> CreateCancelValuesEvent(
double time,
std::unique_ptr<ParamEvent> saved_event);
// Needed for creating a saved event where we want to supply all
// the possible parameters because we're mostly copying an
// existing event.
static std::unique_ptr<ParamEvent> CreateGeneralEvent(
Type,
float value,
double time,
float initial_value,
double call_time,
double time_constant,
double duration,
Vector<float>& curve,
double curve_points_per_second,
float curve_end_value,
std::unique_ptr<ParamEvent> saved_event);
static bool EventPreceeds(const std::unique_ptr<ParamEvent>& a,
const std::unique_ptr<ParamEvent>& b) {
return a->Time() < b->Time();
}
Type GetType() const { return type_; }
float Value() const { return value_; }
double Time() const { return time_; }
void SetTime(double new_time) { time_ = new_time; }
double TimeConstant() const { return time_constant_; }
double Duration() const { return duration_; }
const Vector<float>& Curve() const { return curve_; }
Vector<float>& Curve() { return curve_; }
float InitialValue() const { return initial_value_; }
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_; }
float CurveEndValue() const { return curve_end_value_; }
// For CancelValues events. Not valid for any other event.
ParamEvent* SavedEvent() const;
bool HasDefaultCancelledValue() const;
void SetCancelledValue(float);
private:
// General event
ParamEvent(Type type,
float value,
double time,
float initial_value,
double call_time,
double time_constant,
double duration,
Vector<float>& curve,
double curve_points_per_second,
float curve_end_value,
std::unique_ptr<ParamEvent> saved_event);
// Create simplest event needing just a value and time, like
// setValueAtTime.
ParamEvent(Type, float value, double time);
// Create a linear or exponential ramp that requires an initial
// value and time in case there is no actual event that preceeds
// this event.
ParamEvent(Type,
float value,
double time,
float initial_value,
double call_time);
// Create an event needing a time constant (setTargetAtTime)
ParamEvent(Type, float value, double time, double time_constant);
// Create a setValueCurve event
ParamEvent(Type,
double time,
double duration,
const Vector<float>& curve,
double curve_points_per_second,
float curve_end_value);
// Create CancelValues event
ParamEvent(Type, double time, std::unique_ptr<ParamEvent> saved_event);
Type type_;
// The value for the event. The interpretation of this depends on
// the event type. Not used for SetValueCurve. For CancelValues,
// it is the end value to use when cancelling a LinearRampToValue
// or ExponentialRampToValue event.
float value_;
// The time for the event. The interpretation of this depends on
// the event type.
double time_;
// Initial value and time to use for linear and exponential ramps that don't
// have a preceding event.
float initial_value_;
double call_time_;
// Only used for SetTarget events
double time_constant_;
// The following items are only used for SetValueCurve events.
//
// The duration of the curve.
double duration_;
// The array of curve points.
Vector<float> curve_;
// The number of curve points per second. it is used to compute
// the curve index step when running the automation.
double curve_points_per_second_;
// The default value to use at the end of the curve. Normally
// it's the last entry in m_curve, but cancelling a SetValueCurve
// will set this to a new value.
float curve_end_value_;
// For CancelValues. If CancelValues is in the middle of an event, this
// holds the event that is being cancelled, so that processing can
// continue as if the event still existed up until we reach the actual
// scheduled cancel time.
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.
bool has_default_cancelled_value_;
};
// State of the timeline for the current event.
struct AutomationState {
// Parameters for the current automation request. Number of
// values to be computed for the automation request
const unsigned number_of_values;
// Start and end frames for this automation request
const size_t start_frame;
const size_t end_frame;
// Sample rate and control rate for this request
const double sample_rate;
const double control_rate;
// Parameters needed for processing the current event.
const size_t fill_to_frame;
const size_t fill_to_end_frame;
// Value and time for the current event
const float value1;
const double time1;
// Value and time for the next event, if any.
const float value2;
const double time2;
// The current event, and it's index in the event vector.
const ParamEvent* event;
const int event_index;
};
void InsertEvent(std::unique_ptr<ParamEvent>, ExceptionState&);
float ValuesForFrameRangeImpl(size_t start_frame,
size_t end_frame,
float default_value,
float* values,
unsigned number_of_values,
double sample_rate,
double control_rate);
// Produce a nice string describing the event in human-readable form.
String EventToString(const ParamEvent&);
// Automation functions that compute the vlaue of the specified
// automation at the specified time.
float LinearRampAtTime(double t,
float value1,
double time1,
float value2,
double time2);
float ExponentialRampAtTime(double t,
float value1,
double time1,
float value2,
double time2);
float TargetValueAtTime(double t,
float value1,
double time1,
float value2,
float time_constant);
float ValueCurveAtTime(double t,
double time1,
double duration,
const float* curve_data,
unsigned curve_length);
// Handles the special case where the first event in the timeline
// starts after |startFrame|. These initial values are filled using
// |defaultValue|. The updated |currentFrame| and |writeIndex| is
// returned.
std::tuple<size_t, unsigned> HandleFirstEvent(float* values,
float default_value,
unsigned number_of_values,
size_t start_frame,
size_t end_frame,
double sample_rate,
size_t current_frame,
unsigned write_index);
// Return true if |currentEvent| starts after |currentFrame|, but
// also takes into account the |nextEvent| if any.
bool IsEventCurrent(const ParamEvent* current_event,
const ParamEvent* next_event,
size_t current_frame,
double sample_rate);
// Clamp event times to current time, if needed.
void ClampToCurrentTime(int number_of_events,
size_t start_frame,
double sample_rate);
// 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,
// return true and also fill in |values| with |defaultValue|.
bool HandleAllEventsInThePast(double current_time,
double sample_rate,
float default_value,
unsigned number_of_values,
float* values);
// Handle processing of CancelValue event. If cancellation happens, value2,
// time2, and nextEventType will be updated with the new value due to
// cancellation. The
std::tuple<float, double, ParamEvent::Type> HandleCancelValues(
const ParamEvent* current_event,
ParamEvent* next_event,
float value2,
double time2);
// Process a SetTarget event and the next event is a
// LinearRampToValue or ExponentialRampToValue event. This requires
// special handling because the ramp should start at whatever value
// the SetTarget event has reached at this time, instead of using
// the value of the SetTarget event.
void ProcessSetTargetFollowedByRamp(int event_index,
ParamEvent*& current_event,
ParamEvent::Type next_event_type,
size_t current_frame,
double sample_rate,
double control_rate,
float& value);
// Handle processing of linearRampEvent, writing the appropriate
// values to |values|. Returns the updated |currentFrame|, last
// computed |value|, and the updated |writeIndex|.
std::tuple<size_t, float, unsigned> ProcessLinearRamp(
const AutomationState& current_state,
float* values,
size_t current_frame,
float value,
unsigned write_index);
// Handle processing of exponentialRampEvent, writing the appropriate
// values to |values|. Returns the updated |currentFrame|, last
// computed |value|, and the updated |writeIndex|.
std::tuple<size_t, float, unsigned> ProcessExponentialRamp(
const AutomationState& current_state,
float* values,
size_t current_frame,
float value,
unsigned write_index);
// Handle processing of SetTargetEvent, writing the appropriate
// values to |values|. Returns the updated |currentFrame|, last
// computed |value|, and the updated |writeIndex|.
std::tuple<size_t, float, unsigned> ProcessSetTarget(
const AutomationState& current_state,
float* values,
size_t current_frame,
float value,
unsigned write_index);
// Handle processing of SetValueCurveEvent, writing the appropriate
// values to |values|. Returns the updated |currentFrame|, last
// computed |value|, and the updated |writeIndex|.
std::tuple<size_t, float, unsigned> ProcessSetValueCurve(
const AutomationState& current_state,
float* values,
size_t current_frame,
float value,
unsigned write_index);
// Handle processing of CancelValuesEvent, writing the appropriate
// values to |values|. Returns the updated |currentFrame|, last
// computed |value|, and the updated |writeIndex|.
std::tuple<size_t, float, unsigned> ProcessCancelValues(
const AutomationState& current_state,
float* values,
size_t current_frame,
float value,
unsigned write_index);
// Fill the output vector |values| with the value |defaultValue|,
// starting at |writeIndex| and continuing up to |endFrame|
// (exclusive). |writeIndex| is updated with the new index.
unsigned FillWithDefault(float* values,
float default_value,
size_t end_frame,
unsigned write_index);
// Vector of all automation events for the AudioParam. Access must
// be locked via m_eventsLock.
Vector<std::unique_ptr<ParamEvent>> events_;
mutable Mutex events_lock_;
// Smoothing (de-zippering)
float smoothed_value_;
};
} // namespace blink
#endif // AudioParamTimeline_h