1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
|
/*
* 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 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.
*/
#pragma once
#include "AudioContext.h"
#include <JavaScriptCore/Forward.h>
#include <wtf/Lock.h>
#include <wtf/TZoneMalloc.h>
#include <wtf/Vector.h>
namespace WebCore {
class AudioParamTimeline {
WTF_MAKE_TZONE_ALLOCATED(AudioParamTimeline);
WTF_MAKE_NONCOPYABLE(AudioParamTimeline);
public:
AudioParamTimeline() = default;
ExceptionOr<void> setValueAtTime(float value, Seconds time);
ExceptionOr<void> linearRampToValueAtTime(float targetValue, Seconds endTime, float currentValue, Seconds currentTime);
ExceptionOr<void> exponentialRampToValueAtTime(float targetValue, Seconds endTime, float currentValue, Seconds currentTime);
ExceptionOr<void> setTargetAtTime(float target, Seconds time, float timeConstant);
ExceptionOr<void> setValueCurveAtTime(Vector<float>&& curve, Seconds time, Seconds duration);
void cancelScheduledValues(Seconds cancelTime);
ExceptionOr<void> cancelAndHoldAtTime(Seconds cancelTime);
// hasValue is set to true if a valid timeline value is returned.
// otherwise defaultValue is returned.
std::optional<float> valueForContextTime(BaseAudioContext&, float defaultValue, float minValue, float maxValue);
// Given the time range, 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 startFrame, size_t endFrame, float defaultValue, float minValue, float maxValue, std::span<float> values, double sampleRate, double controlRate);
bool hasValues(size_t startFrame, double sampleRate) const;
private:
class ParamEvent {
WTF_MAKE_TZONE_ALLOCATED(ParamEvent);
public:
enum Type {
SetValue,
LinearRampToValue,
ExponentialRampToValue,
SetTarget,
SetValueCurve,
CancelValues,
LastType
};
struct SavedEvent {
Type type;
float value;
Seconds time;
};
static ParamEvent createSetValueEvent(float value, Seconds time);
static ParamEvent createLinearRampEvent(float value, Seconds time);
static ParamEvent createExponentialRampEvent(float value, Seconds time);
static ParamEvent createSetTargetEvent(float target, Seconds time, float timeConstant);
static ParamEvent createSetValueCurveEvent(Vector<float>&& curve, Seconds time, Seconds duration);
static ParamEvent createCancelValuesEvent(Seconds cancelTime, std::optional<SavedEvent>&&);
ParamEvent(Type type, float value, Seconds time, float timeConstant, Seconds duration, Vector<float>&& curve, double curvePointsPerSecond, float curveEndValue, std::optional<SavedEvent>&& savedEvent)
: m_type(type)
, m_value(value)
, m_time(time)
, m_timeConstant(timeConstant)
, m_duration(duration)
, m_curve(WTFMove(curve))
, m_curvePointsPerSecond(curvePointsPerSecond)
, m_curveEndValue(curveEndValue)
, m_savedEvent(WTFMove(savedEvent))
{
}
Type type() const { return m_type; }
float value() const { return m_value; }
Seconds time() const { return m_time; }
float timeConstant() const { return m_timeConstant; }
Seconds duration() const { return m_duration; }
const Vector<float>& curve() const { return m_curve; }
SavedEvent* savedEvent() { return m_savedEvent ? &m_savedEvent.value() : nullptr; }
void setCancelledValue(float cancelledValue)
{
ASSERT(m_type == Type::CancelValues);
m_value = cancelledValue;
m_hasDefaultCancelledValue = true;
}
bool hasDefaultCancelledValue() const
{
ASSERT(m_type == Type::CancelValues);
return m_hasDefaultCancelledValue;
}
double curvePointsPerSecond() const { return m_curvePointsPerSecond; }
float curveEndValue() const { return m_curveEndValue; }
private:
Type m_type;
float m_value { 0 };
Seconds m_time;
// Only used for SetTarget events.
float m_timeConstant { 0 };
// The duration of the curve.
Seconds m_duration;
// The array of curve points.
Vector<float> m_curve;
// The number of curve points per second. it is used to compute
// the curve index step when running the automation.
double m_curvePointsPerSecond { 0 };
// 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 m_curveEndValue { 0 };
// True if a default value has been assigned to the CancelValues event.
bool m_hasDefaultCancelledValue { false };
// 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::optional<SavedEvent> m_savedEvent;
};
// 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 size_t numberOfValues;
// Start and end frames for this automation request
const size_t startFrame;
const size_t endFrame;
// Sample rate and control rate for this request
const double sampleRate;
const double controlRate;
const double samplingPeriod;
// Parameters needed for processing the current event.
const size_t fillToFrame;
const size_t fillToEndFrame;
// Value and time for the current event
const float value1;
const Seconds time1;
// Value and time for the next event, if any.
const float value2;
const Seconds time2;
// The current event, and it's index in the event vector.
const ParamEvent* event;
const int eventIndex;
};
void removeCancelledEvents(size_t firstEventToRemove) WTF_REQUIRES_LOCK(m_eventsLock);
void removeOldEvents(size_t eventCount) WTF_REQUIRES_LOCK(m_eventsLock);
ExceptionOr<void> insertEvent(ParamEvent&&) WTF_REQUIRES_LOCK(m_eventsLock);
float valuesForFrameRangeImpl(size_t startFrame, size_t endFrame, float defaultValue, std::span<float> values, double sampleRate, double controlRate) WTF_REQUIRES_LOCK(m_eventsLock);
float linearRampAtTime(Seconds t, float value1, Seconds time1, float value2, Seconds time2);
float exponentialRampAtTime(Seconds t, float value1, Seconds time1, float value2, Seconds time2);
float valueCurveAtTime(Seconds t, Seconds time1, Seconds duration, std::span<const float> curveData, size_t curveLength);
void handleCancelValues(ParamEvent&, ParamEvent* nextEvent, float& value2, Seconds& time2, ParamEvent::Type& nextEventType);
bool isEventCurrent(const ParamEvent&, const ParamEvent* nextEvent, size_t currentFrame, double sampleRate) const;
void processLinearRamp(const AutomationState&, std::span<float> values, size_t& currentFrame, float& value, unsigned& writeIndex);
void processExponentialRamp(const AutomationState&, std::span<float> values, size_t& currentFrame, float& value, unsigned& writeIndex);
void processCancelValues(const AutomationState&, std::span<float> values, size_t& currentFrame, float& value, unsigned& writeIndex) WTF_REQUIRES_LOCK(m_eventsLock);
void processSetTarget(const AutomationState&, std::span<float> values, size_t& currentFrame, float& value, unsigned& writeIndex);
void processSetValueCurve(const AutomationState&, std::span<float> values, size_t& currentFrame, float& value, unsigned& writeIndex);
void processSetTargetFollowedByRamp(int eventIndex, ParamEvent*&, ParamEvent::Type nextEventType, size_t currentFrame, double samplingPeriod, double controlRate, float& value) WTF_REQUIRES_LOCK(m_eventsLock);
Vector<ParamEvent> m_events WTF_GUARDED_BY_LOCK(m_eventsLock);
mutable Lock m_eventsLock;
};
} // namespace WebCore
|