From e7fa51e72605055bd0a390d9d354c5009a02f556 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Fri, 1 Mar 2013 17:06:03 -0500 Subject: [PATCH] Bug 836076 - Part 5: Provide an API for converting event times to tick values; r=roc --- content/media/AudioEventTimeline.h | 67 +++++++++++++++--- .../compiledtest/TestAudioEventTimeline.cpp | 70 +++++++++---------- 2 files changed, 92 insertions(+), 45 deletions(-) diff --git a/content/media/AudioEventTimeline.h b/content/media/AudioEventTimeline.h index 579e45f48e24..ace96e4d5d6a 100644 --- a/content/media/AudioEventTimeline.h +++ b/content/media/AudioEventTimeline.h @@ -33,6 +33,9 @@ struct AudioTimelineEvent { : mType(aType) , mTimeConstant(aTimeConstant) , mDuration(aDuration) +#ifdef DEBUG + , mTimeIsInTicks(false) +#endif { if (aType == AudioTimelineEvent::SetValueCurve) { mCurve = aCurve; @@ -51,17 +54,39 @@ struct AudioTimelineEvent { IsValid(mDuration); } + template + TimeType Time() const; + + void SetTimeInTicks(int64_t aTimeInTicks) + { + mTimeInTicks = aTimeInTicks; +#ifdef DEBUG + mTimeIsInTicks = true; +#endif + } + Type mType; union { float mValue; uint32_t mCurveLength; }; union { - double mTime; + // The time for an event can either be in absolute value or in ticks. + // Initially the time of the event is always in absolute value. + // In order to convert it to ticks, call SetTimeInTicks. Once this + // method has been called for an event, the time cannot be converted + // back to absolute value. + union { + double mTime; + int64_t mTimeInTicks; + }; float* mCurve; }; double mTimeConstant; double mDuration; +#ifdef DEBUG + bool mTimeIsInTicks; +#endif private: static bool IsValid(double value) @@ -70,6 +95,20 @@ private: } }; +template <> +inline double AudioTimelineEvent::Time() const +{ + MOZ_ASSERT(!mTimeIsInTicks); + return mTime; +} + +template <> +inline int64_t AudioTimelineEvent::Time() const +{ + MOZ_ASSERT(mTimeIsInTicks); + return mTimeInTicks; +} + /** * This class will be instantiated with different template arguments for testing and * production code. @@ -151,7 +190,8 @@ public: } // This method computes the AudioParam value at a given time based on the event timeline - float GetValueAtTime(double aTime) const + template + float GetValueAtTime(TimeType aTime) const { const AudioTimelineEvent* previous = nullptr; const AudioTimelineEvent* next = nullptr; @@ -163,17 +203,17 @@ public: case AudioTimelineEvent::SetTarget: case AudioTimelineEvent::LinearRamp: case AudioTimelineEvent::ExponentialRamp: - if (aTime == mEvents[i].mTime) { + if (aTime == mEvents[i].template Time()) { // Find the last event with the same time do { ++i; } while (i < mEvents.Length() && - aTime == mEvents[i].mTime); + aTime == mEvents[i].template Time()); return mEvents[i - 1].mValue; } previous = next; next = &mEvents[i]; - if (aTime < mEvents[i].mTime) { + if (aTime < mEvents[i].template Time()) { bailOut = true; } break; @@ -204,10 +244,10 @@ public: return mValue; case AudioTimelineEvent::LinearRamp: // 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->template Time(), next->mValue, aTime); case AudioTimelineEvent::ExponentialRamp: // 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->template Time(), next->mValue, aTime); case AudioTimelineEvent::SetValueCurve: // TODO: implement return 0.0f; @@ -218,7 +258,7 @@ public: // SetTarget nodes can be handled no matter what their next node is (if they have one) if (previous->mType == AudioTimelineEvent::SetTarget) { // Follow the curve, without regard to the next node - return ExponentialApproach(previous->mTime, mValue, previous->mValue, + return ExponentialApproach(previous->template Time(), mValue, previous->mValue, previous->mTimeConstant, aTime); } @@ -244,9 +284,9 @@ public: // First, handle the case where our range ends up in a ramp event switch (next->mType) { case AudioTimelineEvent::LinearRamp: - return LinearInterpolate(previous->mTime, previous->mValue, next->mTime, next->mValue, aTime); + return LinearInterpolate(previous->template Time(), previous->mValue, next->template Time(), next->mValue, aTime); case AudioTimelineEvent::ExponentialRamp: - return ExponentialInterpolate(previous->mTime, previous->mValue, next->mTime, next->mValue, aTime); + return ExponentialInterpolate(previous->template Time(), previous->mValue, next->template Time(), next->mValue, aTime); case AudioTimelineEvent::SetValue: case AudioTimelineEvent::SetTarget: case AudioTimelineEvent::SetValueCurve: @@ -293,6 +333,13 @@ public: return v1 + (v0 - v1) * expf(-(t - t0) / timeConstant); } + void ConvertEventTimesToTicks(int64_t (*aConvertor)(double aTime, void* aClosure), void* aClosure) + { + for (unsigned i = 0; i < mEvents.Length(); ++i) { + mEvents[i].SetTimeInTicks(aConvertor(mEvents[i].template Time(), aClosure)); + } + } + private: const AudioTimelineEvent* GetPreviousEvent(double aTime) const { diff --git a/content/media/webaudio/compiledtest/TestAudioEventTimeline.cpp b/content/media/webaudio/compiledtest/TestAudioEventTimeline.cpp index 5da3f4d7e136..6e0cabe17f99 100644 --- a/content/media/webaudio/compiledtest/TestAudioEventTimeline.cpp +++ b/content/media/webaudio/compiledtest/TestAudioEventTimeline.cpp @@ -91,14 +91,14 @@ void TestSpecExample() ErrorResultMock rv; // This test is copied from the example in the Web Audio spec - const float t0 = 0.0, - t1 = 0.1, - t2 = 0.2, - t3 = 0.3, - t4 = 0.4, - t5 = 0.6, - t6 = 0.7/*, - t7 = 1.0*/; + const double t0 = 0.0, + t1 = 0.1, + t2 = 0.2, + t3 = 0.3, + t4 = 0.4, + t5 = 0.6, + t6 = 0.7/*, + t7 = 1.0*/; timeline.SetValueAtTime(0.2f, t0, rv); is(rv, NS_OK, "SetValueAtTime succeeded"); timeline.SetValueAtTime(0.3f, t1, rv); @@ -115,22 +115,22 @@ void TestSpecExample() is(rv, NS_OK, "ExponentialRampToValueAtTime succeeded"); // TODO: Add the SetValueCurveAtTime test - is(timeline.GetValueAtTime(0.0f), 0.2f, "Correct value"); - is(timeline.GetValueAtTime(0.05f), 0.2f, "Correct value"); - is(timeline.GetValueAtTime(0.1f), 0.3f, "Correct value"); - is(timeline.GetValueAtTime(0.15f), 0.3f, "Correct value"); - is(timeline.GetValueAtTime(0.2f), 0.4f, "Correct value"); - is(timeline.GetValueAtTime(0.25f), (0.4f + 1.0f) / 2, "Correct value"); - is(timeline.GetValueAtTime(0.3f), 1.0f, "Correct value"); - is(timeline.GetValueAtTime(0.35f), (1.0f + 0.15f) / 2, "Correct value"); - is(timeline.GetValueAtTime(0.4f), 0.15f, "Correct value"); - is(timeline.GetValueAtTime(0.45f), (0.15f * powf(0.75f / 0.15f, 0.05f / 0.2f)), "Correct value"); - is(timeline.GetValueAtTime(0.5f), (0.15f * powf(0.75f / 0.15f, 0.5f)), "Correct value"); - is(timeline.GetValueAtTime(0.55f), (0.15f * powf(0.75f / 0.15f, 0.15f / 0.2f)), "Correct value"); - is(timeline.GetValueAtTime(0.6f), 0.75f, "Correct value"); - is(timeline.GetValueAtTime(0.65f), (0.75f * powf(0.05 / 0.75f, 0.5f)), "Correct value"); - is(timeline.GetValueAtTime(0.7f), 0.05f, "Correct value"); - is(timeline.GetValueAtTime(1.0f), 0.05f, "Correct value"); + is(timeline.GetValueAtTime(0.0), 0.2f, "Correct value"); + is(timeline.GetValueAtTime(0.05), 0.2f, "Correct value"); + is(timeline.GetValueAtTime(0.1), 0.3f, "Correct value"); + is(timeline.GetValueAtTime(0.15), 0.3f, "Correct value"); + is(timeline.GetValueAtTime(0.2), 0.4f, "Correct value"); + is(timeline.GetValueAtTime(0.25), (0.4f + 1.0f) / 2, "Correct value"); + is(timeline.GetValueAtTime(0.3), 1.0f, "Correct value"); + is(timeline.GetValueAtTime(0.35), (1.0f + 0.15f) / 2, "Correct value"); + is(timeline.GetValueAtTime(0.4), 0.15f, "Correct value"); + is(timeline.GetValueAtTime(0.45), (0.15f * powf(0.75f / 0.15f, 0.05f / 0.2f)), "Correct value"); + is(timeline.GetValueAtTime(0.5), (0.15f * powf(0.75f / 0.15f, 0.5f)), "Correct value"); + is(timeline.GetValueAtTime(0.55), (0.15f * powf(0.75f / 0.15f, 0.15f / 0.2f)), "Correct value"); + is(timeline.GetValueAtTime(0.6), 0.75f, "Correct value"); + is(timeline.GetValueAtTime(0.65), (0.75f * powf(0.05 / 0.75f, 0.5f)), "Correct value"); + is(timeline.GetValueAtTime(0.7), 0.05f, "Correct value"); + is(timeline.GetValueAtTime(1.0), 0.05f, "Correct value"); } void TestInvalidEvents() @@ -189,11 +189,11 @@ void TestEventReplacement() timeline.SetValueAtTime(20.0f, 0.1, rv); is(rv, NS_OK, "Event scheduling should be successful"); is(timeline.GetEventCount(), 1u, "Event should be replaced"); - is(timeline.GetValueAtTime(0.1f), 20.0f, "The first event should be overwritten"); + is(timeline.GetValueAtTime(0.1), 20.0f, "The first event should be overwritten"); timeline.LinearRampToValueAtTime(30.0f, 0.1, rv); is(rv, NS_OK, "Event scheduling should be successful"); is(timeline.GetEventCount(), 2u, "Different event type should be appended"); - is(timeline.GetValueAtTime(0.1f), 30.0f, "The first event should be overwritten"); + is(timeline.GetValueAtTime(0.1), 30.0f, "The first event should be overwritten"); } void TestEventRemoval() @@ -222,7 +222,7 @@ void TestBeforeFirstEvent() ErrorResultMock rv; timeline.SetValueAtTime(20.0f, 1.0, rv); - is(timeline.GetValueAtTime(0.5f), 10.0f, "Retrun the default value before the first event"); + is(timeline.GetValueAtTime(0.5), 10.0f, "Retrun the default value before the first event"); } void TestAfterLastValueEvent() @@ -232,7 +232,7 @@ void TestAfterLastValueEvent() ErrorResultMock rv; timeline.SetValueAtTime(20.0f, 1.0, rv); - is(timeline.GetValueAtTime(1.5f), 20.0f, "Return the last value after the last SetValue event"); + is(timeline.GetValueAtTime(1.5), 20.0f, "Return the last value after the last SetValue event"); } void TestAfterLastTargetValueEvent() @@ -242,7 +242,7 @@ void TestAfterLastTargetValueEvent() ErrorResultMock rv; timeline.SetTargetAtTime(20.0f, 1.0, 5.0, rv); - is(timeline.GetValueAtTime(10.f), (20.f + (10.f - 20.f) * expf(-9.0f / 5.0f)), "Return the value after the last SetTarget event based on the curve"); + is(timeline.GetValueAtTime(10.), (20.f + (10.f - 20.f) * expf(-9.0f / 5.0f)), "Return the value after the last SetTarget event based on the curve"); } void TestAfterLastTargetValueEventWithValueSet() @@ -253,7 +253,7 @@ void TestAfterLastTargetValueEventWithValueSet() timeline.SetValue(50.f); timeline.SetTargetAtTime(20.0f, 1.0, 5.0, rv); - is(timeline.GetValueAtTime(10.f), (20.f + (50.f - 20.f) * expf(-9.0f / 5.0f)), "Return the value after SetValue and the last SetTarget event based on the curve"); + is(timeline.GetValueAtTime(10.), (20.f + (50.f - 20.f) * expf(-9.0f / 5.0f)), "Return the value after SetValue and the last SetTarget event based on the curve"); } void TestValue() @@ -279,7 +279,7 @@ void TestLinearRampAtZero() ErrorResultMock rv; timeline.LinearRampToValueAtTime(20.0f, 0.0, rv); - is(timeline.GetValueAtTime(0.0f), 20.0f, "Should get the correct value when t0 == t1 == 0"); + is(timeline.GetValueAtTime(0.0), 20.0f, "Should get the correct value when t0 == t1 == 0"); } void TestExponentialRampAtZero() @@ -289,7 +289,7 @@ void TestExponentialRampAtZero() ErrorResultMock rv; timeline.ExponentialRampToValueAtTime(20.0f, 0.0, rv); - is(timeline.GetValueAtTime(0.0f), 20.0f, "Should get the correct value when t0 == t1 == 0"); + is(timeline.GetValueAtTime(0.0), 20.0f, "Should get the correct value when t0 == t1 == 0"); } void TestLinearRampAtSameTime() @@ -300,7 +300,7 @@ void TestLinearRampAtSameTime() timeline.SetValueAtTime(5.0f, 1.0, rv); timeline.LinearRampToValueAtTime(20.0f, 1.0, rv); - is(timeline.GetValueAtTime(1.0f), 20.0f, "Should get the correct value when t0 == t1"); + is(timeline.GetValueAtTime(1.0), 20.0f, "Should get the correct value when t0 == t1"); } void TestExponentialRampAtSameTime() @@ -311,7 +311,7 @@ void TestExponentialRampAtSameTime() timeline.SetValueAtTime(5.0f, 1.0, rv); timeline.ExponentialRampToValueAtTime(20.0f, 1.0, rv); - is(timeline.GetValueAtTime(1.0f), 20.0f, "Should get the correct value when t0 == t1"); + is(timeline.GetValueAtTime(1.0), 20.0f, "Should get the correct value when t0 == t1"); } void TestSetTargetZeroTimeConstant() @@ -321,7 +321,7 @@ void TestSetTargetZeroTimeConstant() ErrorResultMock rv; timeline.SetTargetAtTime(20.0f, 1.0, 0.0, rv); - is(timeline.GetValueAtTime(10.f), 20.f, "Should get the correct value with timeConstant == 0"); + is(timeline.GetValueAtTime(10.), 20.f, "Should get the correct value with timeConstant == 0"); } void TestExponentialInvalidPreviousZeroValue()