Bug 1313058 - Fix SetValueCurveAtTime interpolation; r=padenot

This interpolates over aCurveLength - 1 steps rather than over
aCurveLength steps as was done before.

Previously we would reach the final value on the curve before
the end of the specified duration. For example, on the curve
[1.0, 0.0] with duration 1000, we would interpolate from 1.0 to
0.0 by time 500 rather than time 1000. With these changes, we
don't reach 0.0 until time 1000, as expected.

This also updates TestSpecExample in TestAudioEventTimeline.cpp
to match the curve in the latest spec.

MozReview-Commit-ID: Cgs8csbRUMh

--HG--
extra : rebase_source : 1960128558ae9174933cd5be3c1fbfcb79f5ba1d
This commit is contained in:
Dan Minor 2016-10-26 10:33:20 -04:00
Родитель 9c3d575a0f
Коммит 98715f6438
4 изменённых файлов: 26 добавлений и 21 удалений

Просмотреть файл

@ -37,11 +37,12 @@ static float ExtractValueFromCurve(double startTime, float* aCurve, uint32_t aCu
if (ratio >= 1.0) {
return aCurve[aCurveLength - 1];
}
uint32_t current = uint32_t(aCurveLength * ratio);
uint32_t current = uint32_t(floor((aCurveLength - 1) * ratio));
uint32_t next = current + 1;
double step = duration / double(aCurveLength - 1);
if (next < aCurveLength) {
double t0 = double(current) / double(aCurveLength) * duration ;
double t1 = double(next) / double(aCurveLength) * duration ;
double t0 = current * step;
double t1 = next * step;
return LinearInterpolate(t0, aCurve[current], t1, aCurve[next], t - startTime);
} else {
return aCurve[current];

Просмотреть файл

@ -102,7 +102,11 @@ void TestSpecExample()
ErrorResultMock rv;
float curve[] = { -1.0f, 0.0f, 1.0f };
uint32_t curveLength = 44100;
float* curve = new float[curveLength];
for (uint32_t i = 0; i < curveLength; ++i) {
curve[i] = sin(M_PI * i / float(curveLength));
}
// This test is copied from the example in the Web Audio spec
const double t0 = 0.0,
@ -127,7 +131,7 @@ void TestSpecExample()
is(rv, NS_OK, "ExponentialRampToValueAtTime succeeded");
timeline.ExponentialRampToValueAtTime(0.05f, t6, rv);
is(rv, NS_OK, "ExponentialRampToValueAtTime succeeded");
timeline.SetValueCurveAtTime(curve, ArrayLength(curve), t6, t7 - t6, rv);
timeline.SetValueCurveAtTime(curve, curveLength, t6, t7 - t6, rv);
is(rv, NS_OK, "SetValueCurveAtTime succeeded");
is(timeline.GetValueAtTime(0.0), 0.2f, "Correct value");
@ -144,10 +148,11 @@ void TestSpecExample()
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.05f / 0.75f, 0.5f)), "Correct value");
is(timeline.GetValueAtTime(0.7), -1.0f, "Correct value");
is(timeline.GetValueAtTime(0.8), 0.0f, "Correct value");
is(timeline.GetValueAtTime(0.9), 1.0f, "Correct value");
is(timeline.GetValueAtTime(1.0), 1.0f, "Correct value");
is(timeline.GetValueAtTime(0.7), 0.0f, "Correct value");
is(timeline.GetValueAtTime(0.85), 1.0f, "Correct value");
is(timeline.GetValueAtTime(1.0), curve[curveLength - 1], "Correct value");
delete[] curve;
}
void TestInvalidEvents()

Просмотреть файл

@ -30,13 +30,14 @@ var gTest = {
this.curve = new Float32Array([1.0, 0.5, 0.75, 0.25]);
var expectedBuffer = context.createBuffer(1, 2048, context.sampleRate);
var data = expectedBuffer.getChannelData(0);
var step = 1024 / 3;
for (var i = 0; i < 2048; ++i) {
if (i < 256) {
data[i] = 1.0 - 0.5*i/256;
} else if (i < 512) {
data[i] = 0.5 + 0.25*(i - 256)/256;
} else if (i < 768) {
data[i] = 0.75 - 0.5*(i - 512)/256;
if (i < step) {
data[i] = 1.0 - 0.5*i/step;
} else if (i < 2*step) {
data[i] = 0.5 + 0.25*(i - step)/step;
} else if (i < 3*step) {
data[i] = 0.75 - 0.5*(i - 2*step)/step;
} else {
data[i] = 0.25;
}

Просмотреть файл

@ -47,15 +47,13 @@ var gTest = {
}
var expectedBuffer = context.createBuffer(1, 2048, context.sampleRate);
for (var i = 0; i < 2048; ++i) {
var t = i / context.sampleRate;
var current = Math.min(99, Math.floor(100 * Math.min(1.0, (t - T0) / this.duration)));
step = 1024.0/99.0;
var current = Math.floor(i / step);
var next = current + 1;
if (next < this.curve.length) {
var t0 = current / this.curve.length * this.duration;
var t1 = next / this.curve.length * this.duration;
expectedBuffer.getChannelData(0)[i] = linearInterpolate(t0, this.curve[current], t1, this.curve[next], t);
expectedBuffer.getChannelData(0)[i] = linearInterpolate(current*step, this.curve[current], next*step, this.curve[next], i);
} else {
expectedBuffer.getChannelData(0)[i] = this.curve[current];
expectedBuffer.getChannelData(0)[i] = this.curve[99];
}
}
return expectedBuffer;