mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 836076 - Part 4: Move AudioEventTimeline::Event outside of AudioEventTimeline to be able to specialize its template members; r=roc
This commit is contained in:
parent
6bc6665342
commit
030416b20c
@ -18,6 +18,58 @@ namespace mozilla {
|
|||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
|
// This is an internal helper class and should not be used outside of this header.
|
||||||
|
struct AudioTimelineEvent {
|
||||||
|
enum Type MOZ_ENUM_TYPE(uint32_t) {
|
||||||
|
SetValue,
|
||||||
|
LinearRamp,
|
||||||
|
ExponentialRamp,
|
||||||
|
SetTarget,
|
||||||
|
SetValueCurve
|
||||||
|
};
|
||||||
|
|
||||||
|
AudioTimelineEvent(Type aType, double aTime, float aValue, double aTimeConstant = 0.0,
|
||||||
|
float aDuration = 0.0, float* aCurve = nullptr, uint32_t aCurveLength = 0)
|
||||||
|
: mType(aType)
|
||||||
|
, mTimeConstant(aTimeConstant)
|
||||||
|
, mDuration(aDuration)
|
||||||
|
{
|
||||||
|
if (aType == AudioTimelineEvent::SetValueCurve) {
|
||||||
|
mCurve = aCurve;
|
||||||
|
mCurveLength = aCurveLength;
|
||||||
|
} else {
|
||||||
|
mValue = aValue;
|
||||||
|
mTime = aTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsValid() const
|
||||||
|
{
|
||||||
|
return IsValid(mTime) &&
|
||||||
|
IsValid(mValue) &&
|
||||||
|
IsValid(mTimeConstant) &&
|
||||||
|
IsValid(mDuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
Type mType;
|
||||||
|
union {
|
||||||
|
float mValue;
|
||||||
|
uint32_t mCurveLength;
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
double mTime;
|
||||||
|
float* mCurve;
|
||||||
|
};
|
||||||
|
double mTimeConstant;
|
||||||
|
double mDuration;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool IsValid(double value)
|
||||||
|
{
|
||||||
|
return MOZ_DOUBLE_IS_FINITE(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class will be instantiated with different template arguments for testing and
|
* This class will be instantiated with different template arguments for testing and
|
||||||
* production code.
|
* production code.
|
||||||
@ -28,58 +80,6 @@ namespace dom {
|
|||||||
template <class ErrorResult>
|
template <class ErrorResult>
|
||||||
class AudioEventTimeline
|
class AudioEventTimeline
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
struct Event {
|
|
||||||
enum Type MOZ_ENUM_TYPE(uint32_t) {
|
|
||||||
SetValue,
|
|
||||||
LinearRamp,
|
|
||||||
ExponentialRamp,
|
|
||||||
SetTarget,
|
|
||||||
SetValueCurve
|
|
||||||
};
|
|
||||||
|
|
||||||
Event(Type aType, double aTime, float aValue, double aTimeConstant = 0.0,
|
|
||||||
float aDuration = 0.0, float* aCurve = nullptr, uint32_t aCurveLength = 0)
|
|
||||||
: mType(aType)
|
|
||||||
, mTimeConstant(aTimeConstant)
|
|
||||||
, mDuration(aDuration)
|
|
||||||
{
|
|
||||||
if (aType == Event::SetValueCurve) {
|
|
||||||
mCurve = aCurve;
|
|
||||||
mCurveLength = aCurveLength;
|
|
||||||
} else {
|
|
||||||
mValue = aValue;
|
|
||||||
mTime = aTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsValid() const
|
|
||||||
{
|
|
||||||
return IsValid(mTime) &&
|
|
||||||
IsValid(mValue) &&
|
|
||||||
IsValid(mTimeConstant) &&
|
|
||||||
IsValid(mDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
Type mType;
|
|
||||||
union {
|
|
||||||
float mValue;
|
|
||||||
uint32_t mCurveLength;
|
|
||||||
};
|
|
||||||
union {
|
|
||||||
double mTime;
|
|
||||||
float* mCurve;
|
|
||||||
};
|
|
||||||
double mTimeConstant;
|
|
||||||
double mDuration;
|
|
||||||
|
|
||||||
private:
|
|
||||||
static bool IsValid(double value)
|
|
||||||
{
|
|
||||||
return MOZ_DOUBLE_IS_FINITE(value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit AudioEventTimeline(float aDefaultValue)
|
explicit AudioEventTimeline(float aDefaultValue)
|
||||||
: mValue(aDefaultValue)
|
: mValue(aDefaultValue)
|
||||||
@ -108,29 +108,29 @@ public:
|
|||||||
|
|
||||||
void SetValueAtTime(float aValue, double aStartTime, ErrorResult& aRv)
|
void SetValueAtTime(float aValue, double aStartTime, ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
InsertEvent(Event(Event::SetValue, aStartTime, aValue), aRv);
|
InsertEvent(AudioTimelineEvent(AudioTimelineEvent::SetValue, aStartTime, aValue), aRv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinearRampToValueAtTime(float aValue, double aEndTime, ErrorResult& aRv)
|
void LinearRampToValueAtTime(float aValue, double aEndTime, ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
InsertEvent(Event(Event::LinearRamp, aEndTime, aValue), aRv);
|
InsertEvent(AudioTimelineEvent(AudioTimelineEvent::LinearRamp, aEndTime, aValue), aRv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExponentialRampToValueAtTime(float aValue, double aEndTime, ErrorResult& aRv)
|
void ExponentialRampToValueAtTime(float aValue, double aEndTime, ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
InsertEvent(Event(Event::ExponentialRamp, aEndTime, aValue), aRv);
|
InsertEvent(AudioTimelineEvent(AudioTimelineEvent::ExponentialRamp, aEndTime, aValue), aRv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetTargetAtTime(float aTarget, double aStartTime, double aTimeConstant, ErrorResult& aRv)
|
void SetTargetAtTime(float aTarget, double aStartTime, double aTimeConstant, ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
InsertEvent(Event(Event::SetTarget, aStartTime, aTarget, aTimeConstant), aRv);
|
InsertEvent(AudioTimelineEvent(AudioTimelineEvent::SetTarget, aStartTime, aTarget, aTimeConstant), aRv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetValueCurveAtTime(const float* aValues, uint32_t aValuesLength, double aStartTime, double aDuration, ErrorResult& aRv)
|
void SetValueCurveAtTime(const float* aValues, uint32_t aValuesLength, double aStartTime, double aDuration, ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
// Note that we will need to copy the buffer here.
|
// Note that we will need to copy the buffer here.
|
||||||
// InsertEvent(Event(Event::SetValueCurve, aStartTime, 0.0f, 0.0f, aDuration, aValues, aValuesLength), aRv);
|
// InsertEvent(AudioTimelineEvent(AudioTimelineEvent::SetValueCurve, aStartTime, 0.0f, 0.0f, aDuration, aValues, aValuesLength), aRv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CancelScheduledValues(double aStartTime)
|
void CancelScheduledValues(double aStartTime)
|
||||||
@ -153,16 +153,16 @@ public:
|
|||||||
// This method computes the AudioParam value at a given time based on the event timeline
|
// This method computes the AudioParam value at a given time based on the event timeline
|
||||||
float GetValueAtTime(double aTime) const
|
float GetValueAtTime(double aTime) const
|
||||||
{
|
{
|
||||||
const Event* previous = nullptr;
|
const AudioTimelineEvent* previous = nullptr;
|
||||||
const Event* next = nullptr;
|
const AudioTimelineEvent* next = nullptr;
|
||||||
|
|
||||||
bool bailOut = false;
|
bool bailOut = false;
|
||||||
for (unsigned i = 0; !bailOut && i < mEvents.Length(); ++i) {
|
for (unsigned i = 0; !bailOut && i < mEvents.Length(); ++i) {
|
||||||
switch (mEvents[i].mType) {
|
switch (mEvents[i].mType) {
|
||||||
case Event::SetValue:
|
case AudioTimelineEvent::SetValue:
|
||||||
case Event::SetTarget:
|
case AudioTimelineEvent::SetTarget:
|
||||||
case Event::LinearRamp:
|
case AudioTimelineEvent::LinearRamp:
|
||||||
case Event::ExponentialRamp:
|
case AudioTimelineEvent::ExponentialRamp:
|
||||||
if (aTime == mEvents[i].mTime) {
|
if (aTime == mEvents[i].mTime) {
|
||||||
// Find the last event with the same time
|
// Find the last event with the same time
|
||||||
do {
|
do {
|
||||||
@ -177,7 +177,7 @@ public:
|
|||||||
bailOut = true;
|
bailOut = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Event::SetValueCurve:
|
case AudioTimelineEvent::SetValueCurve:
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -198,17 +198,17 @@ public:
|
|||||||
// If the requested time is before all of the existing events
|
// If the requested time is before all of the existing events
|
||||||
if (!previous) {
|
if (!previous) {
|
||||||
switch (next->mType) {
|
switch (next->mType) {
|
||||||
case Event::SetValue:
|
case AudioTimelineEvent::SetValue:
|
||||||
case Event::SetTarget:
|
case AudioTimelineEvent::SetTarget:
|
||||||
// The requested time is before the first event
|
// The requested time is before the first event
|
||||||
return mValue;
|
return mValue;
|
||||||
case Event::LinearRamp:
|
case AudioTimelineEvent::LinearRamp:
|
||||||
// Use t=0 as T0 and v=defaultValue as V0
|
// Use t=0 as T0 and v=defaultValue as V0
|
||||||
return LinearInterpolate(0.0, mValue, next->mTime, next->mValue, aTime);
|
return LinearInterpolate(0.0, mValue, next->mTime, next->mValue, aTime);
|
||||||
case Event::ExponentialRamp:
|
case AudioTimelineEvent::ExponentialRamp:
|
||||||
// Use t=0 as T0 and v=defaultValue as V0
|
// Use t=0 as T0 and v=defaultValue as V0
|
||||||
return ExponentialInterpolate(0.0, mValue, next->mTime, next->mValue, aTime);
|
return ExponentialInterpolate(0.0, mValue, next->mTime, next->mValue, aTime);
|
||||||
case Event::SetValueCurve:
|
case AudioTimelineEvent::SetValueCurve:
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
@ -216,7 +216,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetTarget nodes can be handled no matter what their next node is (if they have one)
|
// SetTarget nodes can be handled no matter what their next node is (if they have one)
|
||||||
if (previous->mType == Event::SetTarget) {
|
if (previous->mType == AudioTimelineEvent::SetTarget) {
|
||||||
// Follow the curve, without regard to the next node
|
// Follow the curve, without regard to the next node
|
||||||
return ExponentialApproach(previous->mTime, mValue, previous->mValue,
|
return ExponentialApproach(previous->mTime, mValue, previous->mValue,
|
||||||
previous->mTimeConstant, aTime);
|
previous->mTimeConstant, aTime);
|
||||||
@ -225,15 +225,15 @@ public:
|
|||||||
// If the requested time is after all of the existing events
|
// If the requested time is after all of the existing events
|
||||||
if (!next) {
|
if (!next) {
|
||||||
switch (previous->mType) {
|
switch (previous->mType) {
|
||||||
case Event::SetValue:
|
case AudioTimelineEvent::SetValue:
|
||||||
case Event::LinearRamp:
|
case AudioTimelineEvent::LinearRamp:
|
||||||
case Event::ExponentialRamp:
|
case AudioTimelineEvent::ExponentialRamp:
|
||||||
// The value will be constant after the last event
|
// The value will be constant after the last event
|
||||||
return previous->mValue;
|
return previous->mValue;
|
||||||
case Event::SetValueCurve:
|
case AudioTimelineEvent::SetValueCurve:
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
case Event::SetTarget:
|
case AudioTimelineEvent::SetTarget:
|
||||||
MOZ_ASSERT(false, "unreached");
|
MOZ_ASSERT(false, "unreached");
|
||||||
}
|
}
|
||||||
MOZ_ASSERT(false, "unreached");
|
MOZ_ASSERT(false, "unreached");
|
||||||
@ -243,28 +243,28 @@ public:
|
|||||||
|
|
||||||
// First, handle the case where our range ends up in a ramp event
|
// First, handle the case where our range ends up in a ramp event
|
||||||
switch (next->mType) {
|
switch (next->mType) {
|
||||||
case Event::LinearRamp:
|
case AudioTimelineEvent::LinearRamp:
|
||||||
return LinearInterpolate(previous->mTime, previous->mValue, next->mTime, next->mValue, aTime);
|
return LinearInterpolate(previous->mTime, previous->mValue, next->mTime, next->mValue, aTime);
|
||||||
case Event::ExponentialRamp:
|
case AudioTimelineEvent::ExponentialRamp:
|
||||||
return ExponentialInterpolate(previous->mTime, previous->mValue, next->mTime, next->mValue, aTime);
|
return ExponentialInterpolate(previous->mTime, previous->mValue, next->mTime, next->mValue, aTime);
|
||||||
case Event::SetValue:
|
case AudioTimelineEvent::SetValue:
|
||||||
case Event::SetTarget:
|
case AudioTimelineEvent::SetTarget:
|
||||||
case Event::SetValueCurve:
|
case AudioTimelineEvent::SetValueCurve:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now handle all other cases
|
// Now handle all other cases
|
||||||
switch (previous->mType) {
|
switch (previous->mType) {
|
||||||
case Event::SetValue:
|
case AudioTimelineEvent::SetValue:
|
||||||
case Event::LinearRamp:
|
case AudioTimelineEvent::LinearRamp:
|
||||||
case Event::ExponentialRamp:
|
case AudioTimelineEvent::ExponentialRamp:
|
||||||
// If the next event type is neither linear or exponential ramp, the
|
// If the next event type is neither linear or exponential ramp, the
|
||||||
// value is constant.
|
// value is constant.
|
||||||
return previous->mValue;
|
return previous->mValue;
|
||||||
case Event::SetValueCurve:
|
case AudioTimelineEvent::SetValueCurve:
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
case Event::SetTarget:
|
case AudioTimelineEvent::SetTarget:
|
||||||
MOZ_ASSERT(false, "unreached");
|
MOZ_ASSERT(false, "unreached");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,18 +294,18 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Event* GetPreviousEvent(double aTime) const
|
const AudioTimelineEvent* GetPreviousEvent(double aTime) const
|
||||||
{
|
{
|
||||||
const Event* previous = nullptr;
|
const AudioTimelineEvent* previous = nullptr;
|
||||||
const Event* next = nullptr;
|
const AudioTimelineEvent* next = nullptr;
|
||||||
|
|
||||||
bool bailOut = false;
|
bool bailOut = false;
|
||||||
for (unsigned i = 0; !bailOut && i < mEvents.Length(); ++i) {
|
for (unsigned i = 0; !bailOut && i < mEvents.Length(); ++i) {
|
||||||
switch (mEvents[i].mType) {
|
switch (mEvents[i].mType) {
|
||||||
case Event::SetValue:
|
case AudioTimelineEvent::SetValue:
|
||||||
case Event::SetTarget:
|
case AudioTimelineEvent::SetTarget:
|
||||||
case Event::LinearRamp:
|
case AudioTimelineEvent::LinearRamp:
|
||||||
case Event::ExponentialRamp:
|
case AudioTimelineEvent::ExponentialRamp:
|
||||||
if (aTime == mEvents[i].mTime) {
|
if (aTime == mEvents[i].mTime) {
|
||||||
// Find the last event with the same time
|
// Find the last event with the same time
|
||||||
do {
|
do {
|
||||||
@ -320,7 +320,7 @@ private:
|
|||||||
bailOut = true;
|
bailOut = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Event::SetValueCurve:
|
case AudioTimelineEvent::SetValueCurve:
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -335,7 +335,7 @@ private:
|
|||||||
return previous;
|
return previous;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InsertEvent(const Event& aEvent, ErrorResult& aRv)
|
void InsertEvent(const AudioTimelineEvent& aEvent, ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
if (!aEvent.IsValid()) {
|
if (!aEvent.IsValid()) {
|
||||||
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
||||||
@ -345,7 +345,7 @@ private:
|
|||||||
// Make sure that non-curve events don't fall within the duration of a
|
// Make sure that non-curve events don't fall within the duration of a
|
||||||
// curve event.
|
// curve event.
|
||||||
for (unsigned i = 0; i < mEvents.Length(); ++i) {
|
for (unsigned i = 0; i < mEvents.Length(); ++i) {
|
||||||
if (mEvents[i].mType == Event::SetValueCurve &&
|
if (mEvents[i].mType == AudioTimelineEvent::SetValueCurve &&
|
||||||
mEvents[i].mTime <= aEvent.mTime &&
|
mEvents[i].mTime <= aEvent.mTime &&
|
||||||
(mEvents[i].mTime + mEvents[i].mDuration) >= aEvent.mTime) {
|
(mEvents[i].mTime + mEvents[i].mDuration) >= aEvent.mTime) {
|
||||||
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
||||||
@ -355,7 +355,7 @@ private:
|
|||||||
|
|
||||||
// Make sure that curve events don't fall in a range which includes other
|
// Make sure that curve events don't fall in a range which includes other
|
||||||
// events.
|
// events.
|
||||||
if (aEvent.mType == Event::SetValueCurve) {
|
if (aEvent.mType == AudioTimelineEvent::SetValueCurve) {
|
||||||
for (unsigned i = 0; i < mEvents.Length(); ++i) {
|
for (unsigned i = 0; i < mEvents.Length(); ++i) {
|
||||||
if (mEvents[i].mTime >= aEvent.mTime &&
|
if (mEvents[i].mTime >= aEvent.mTime &&
|
||||||
mEvents[i].mTime <= (aEvent.mTime + aEvent.mDuration)) {
|
mEvents[i].mTime <= (aEvent.mTime + aEvent.mDuration)) {
|
||||||
@ -366,12 +366,12 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure that invalid values are not used for exponential curves
|
// Make sure that invalid values are not used for exponential curves
|
||||||
if (aEvent.mType == Event::ExponentialRamp) {
|
if (aEvent.mType == AudioTimelineEvent::ExponentialRamp) {
|
||||||
if (aEvent.mValue <= 0.f) {
|
if (aEvent.mValue <= 0.f) {
|
||||||
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const Event* previousEvent = GetPreviousEvent(aEvent.mTime);
|
const AudioTimelineEvent* previousEvent = GetPreviousEvent(aEvent.mTime);
|
||||||
if (previousEvent) {
|
if (previousEvent) {
|
||||||
if (previousEvent->mValue <= 0.f) {
|
if (previousEvent->mValue <= 0.f) {
|
||||||
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
||||||
@ -418,7 +418,7 @@ private:
|
|||||||
// and that is the reason why we're using a simple array as the data structure.
|
// and that is the reason why we're using a simple array as the data structure.
|
||||||
// We can optimize this in the future if the performance of the array ends up
|
// We can optimize this in the future if the performance of the array ends up
|
||||||
// being a bottleneck.
|
// being a bottleneck.
|
||||||
nsTArray<Event> mEvents;
|
nsTArray<AudioTimelineEvent> mEvents;
|
||||||
float mValue;
|
float mValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user