⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 267381 in webkit


Ignore:
Timestamp:
Sep 21, 2020, 4:14:06 PM (6 years ago)
Author:
Chris Dumez
Message:

Properly handle AudioParam.setTargetAtTime() followed by a ramp
https://bugs.webkit.org/show_bug.cgi?id=216804

Reviewed by Darin Adler.

Source/WebCore:

Properly handle AudioParam.setTargetAtTime() followed by a ramp:

This is a merge of the following Blink change:

No new tests, rebaselined existing test.

  • Modules/webaudio/AudioParamTimeline.cpp:

(WebCore::AudioParamTimeline::valuesForTimeRangeImpl):
(WebCore::AudioParamTimeline::processSetTargetFollowedByRamp):

  • Modules/webaudio/AudioParamTimeline.h:

LayoutTests:

Rebaseline test that is now passing.

  • webaudio/AudioParam/audioparam-setTargetAtTime-continuous-expected.txt:
Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r267376 r267381  
     12020-09-21  Chris Dumez  <cdumez@apple.com>
     2
     3        Properly handle AudioParam.setTargetAtTime() followed by a ramp
     4        https://bugs.webkit.org/show_bug.cgi?id=216804
     5
     6        Reviewed by Darin Adler.
     7
     8        Rebaseline test that is now passing.
     9
     10        * webaudio/AudioParam/audioparam-setTargetAtTime-continuous-expected.txt:
     11
    1122020-09-21  Chris Dumez  <cdumez@apple.com>
    213
  • trunk/LayoutTests/webaudio/AudioParam/audioparam-setTargetAtTime-continuous-expected.txt

    r267367 r267381  
    99PASS   Linear ramp: Initial part equals [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}.
    1010PASS   Linear ramp: SetTarget part was correctly replaced by the ramp
    11 FAIL X Linear ramp does not equal [1,1.0004401408450705,1.0008802816901408,1.0013204225352113,1.0017605633802817,1.002200704225352,1.0026408450704225,1.003080985915493,1.0035211267605635,1.0039612676056338,1.0044014084507042,1.0048415492957747,1.005281690140845,1.0057218309859155,1.006161971830986,1.0066021126760563...] with an element-wise tolerance of {"absoluteThreshold":0.00000126765,"relativeThreshold":0}.
    12         Index   Actual                  Expected                AbsError                RelError                Test threshold
    13         [0]     0.0000000000000000e+0   1.0000000000000000e+0   1.0000000000000000e+0   1.0000000000000000e+0   1.2676500000000001e-6
    14         [1]     8.8028167374432087e-4   1.0004401408450705e+0   9.9955985917132617e-1   9.9912010560371878e-1   1.2676500000000001e-6
    15         [2]     1.7605633474886417e-3   1.0008802816901408e+0   9.9911971834265212e-1   9.9824098508113712e-1   1.2676500000000001e-6
    16         [3]     2.6408447884023190e-3   1.0013204225352113e+0   9.9867957774680893e-1   9.9736263764428568e-1   1.2676500000000001e-6
    17         [4]     3.5211266949772835e-3   1.0017605633802817e+0   9.9823943668530446e-1   9.9648506157689443e-1   1.2676500000000001e-6
    18         ...and 2267 more errors.
    19         Max AbsError of 1.0000000000000000e+0 at index of 0.
    20         Max RelError of 1.0000000000000000e+0 at index of 0.
    21  assert_true: expected true got false
     11PASS   Linear ramp equals [expected array] with an element-wise tolerance of {"absoluteThreshold":0.00000126765,"relativeThreshold":0}.
    2212PASS   Linear ramp: Tail part equals [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}.
    23 FAIL < [linear ramp replace] 1 out of 4 assertions were failed. assert_true: expected true got false
     13PASS < [linear ramp replace] All assertions passed. (total 4 assertions)
    2414PASS > [delayed linear ramp] 
    2515PASS   Delayed linear ramp: Initial part equals [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}.
    2616PASS   Delayed linear ramp: SetTarget part equals [expected array] with an element-wise tolerance of {"absoluteThreshold":3.43632e-7,"relativeThreshold":0}.
    27 FAIL X Delayed linear ramp does not equal [0.44932896411722156,0.45015029411504087,0.4509716241128601,0.4517929541106794,0.45261428410849863,0.45343561410631794,0.4542569441041372,0.45507827410195645,0.45589960409977576,0.45672093409759495,0.4575422640954142,0.4583635940932335,0.45918492409105277,0.460006254088872,0.46082758408669133,0.4616489140845106...] with an element-wise tolerance of {"absoluteThreshold":0.00000107972,"relativeThreshold":0}.
    28         Index   Actual                  Expected                AbsError                RelError                Test threshold
    29         [0]     3.3802819252014160e-1   4.4932896411722156e-1   1.1130077159707996e-1   2.4770442256209341e-1   1.0797199999999999e-6
    30         [1]     3.3890849351882935e-1   4.5015029411504087e-1   1.1124180059621153e-1   2.4712146598705201e-1   1.0797199999999999e-6
    31         [2]     3.3978873491287231e-1   4.5097162411286013e-1   1.1118288919998781e-1   2.4654076499536740e-1   1.0797199999999999e-6
    32         [3]     3.4066903591156006e-1   4.5179295411067938e-1   1.1112391819911932e-1   2.4596204342730055e-1   1.0797199999999999e-6
    33         [4]     3.4154930710792542e-1   4.5261428410849863e-1   1.1106497700057322e-1   2.4538548804162183e-1   1.0797199999999999e-6
    34         ...and 1883 more errors.
    35         Max AbsError of 1.1130077159707996e-1 at index of 0.
    36         Max RelError of 2.4770442256209341e-1 at index of 0.
    37  assert_true: expected true got false
     17PASS   Delayed linear ramp equals [expected array] with an element-wise tolerance of {"absoluteThreshold":0.00000107972,"relativeThreshold":0}.
    3818PASS   Delayed linear ramp: Tail part equals [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}.
    39 FAIL < [delayed linear ramp] 1 out of 4 assertions were failed. assert_true: expected true got false
     19PASS < [delayed linear ramp] All assertions passed. (total 4 assertions)
    4020PASS > [expo ramp replace] 
    4121PASS   Exponential ramp: Initial part equals [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}.
    4222PASS   Exponential ramp: SetTarget part was correctly replaced by the ramp
    43 FAIL X Exponential ramp does not equal [1,1.00030517578125,1.0006103515625,1.0009156465530396,1.0012210607528687,1.0015265941619873,1.001832127571106,1.0021378993988037,1.0024436712265015,1.0027495622634888,1.003055453300476,1.0033615827560425,1.0036677122116089,1.0039739608764648,1.0042803287506104,1.0045866966247559...] with an element-wise tolerance of {"absoluteThreshold":0.0000114441,"relativeThreshold":0}.
    44         Index   Actual                  Expected                AbsError                RelError                Test threshold
    45         [0]     0.0000000000000000e+0   1.0000000000000000e+0   1.0000000000000000e+0   1.0000000000000000e+0   1.1444099999999999e-5
    46         [1]     0.0000000000000000e+0   1.0003051757812500e+0   1.0003051757812500e+0   1.0000000000000000e+0   1.1444099999999999e-5
    47         [2]     0.0000000000000000e+0   1.0006103515625000e+0   1.0006103515625000e+0   1.0000000000000000e+0   1.1444099999999999e-5
    48         [3]     0.0000000000000000e+0   1.0009156465530396e+0   1.0009156465530396e+0   1.0000000000000000e+0   1.1444099999999999e-5
    49         [4]     0.0000000000000000e+0   1.0012210607528687e+0   1.0012210607528687e+0   1.0000000000000000e+0   1.1444099999999999e-5
    50         ...and 2267 more errors.
    51         Max AbsError of 1.9993898868560791e+0 at index of 2271.
    52         [2271]  0.0000000000000000e+0   1.9993898868560791e+0   1.9993898868560791e+0   1.0000000000000000e+0   1.1444099999999999e-5
    53         Max RelError of 1.0000000000000000e+0 at index of 0.
    54  assert_true: expected true got false
     23PASS   Exponential ramp equals [expected array] with an element-wise tolerance of {"absoluteThreshold":0.0000114441,"relativeThreshold":0}.
    5524PASS   Exponential ramp: Tail part equals [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}.
    56 FAIL < [expo ramp replace] 1 out of 4 assertions were failed. assert_true: expected true got false
     25PASS < [expo ramp replace] All assertions passed. (total 4 assertions)
    5726PASS > [delayed expo ramp] 
    5827PASS   Delayed exponential ramp: Initial part equals [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}.
    5928PASS   Delayed exponential ramp: SetTarget part equals [expected array] with an element-wise tolerance of {"absoluteThreshold":3.43632e-7,"relativeThreshold":0}.
    60 FAIL X Delayed exponential ramp does not equal [0.4493289589881897,0.4496844708919525,0.45004022121429443,0.4503962993621826,0.4507526457309723,0.45110926032066345,0.4514661729335785,0.451823353767395,0.4521808326244354,0.4525385797023773,0.4528966248035431,0.45325493812561035,0.4536135494709015,0.4539724290370941,0.4543316066265106,0.4546910524368286...] with an element-wise tolerance of {"absoluteThreshold":0.00000429154,"relativeThreshold":0}.
    61         Index   Actual                  Expected                AbsError                RelError                Test threshold
    62         [0]     0.0000000000000000e+0   4.4932895898818970e-1   4.4932895898818970e-1   1.0000000000000000e+0   4.2915399999999997e-6
    63         [1]     0.0000000000000000e+0   4.4968447089195251e-1   4.4968447089195251e-1   1.0000000000000000e+0   4.2915399999999997e-6
    64         [2]     0.0000000000000000e+0   4.5004022121429443e-1   4.5004022121429443e-1   1.0000000000000000e+0   4.2915399999999997e-6
    65         [3]     0.0000000000000000e+0   4.5039629936218262e-1   4.5039629936218262e-1   1.0000000000000000e+0   4.2915399999999997e-6
    66         [4]     0.0000000000000000e+0   4.5075264573097229e-1   4.5075264573097229e-1   1.0000000000000000e+0   4.2915399999999997e-6
    67         ...and 1883 more errors.
    68         Max AbsError of 1.9984188079833984e+0 at index of 1887.
    69         [1887]  0.0000000000000000e+0   1.9984188079833984e+0   1.9984188079833984e+0   1.0000000000000000e+0   4.2915399999999997e-6
    70         Max RelError of 1.0000000000000000e+0 at index of 0.
    71  assert_true: expected true got false
     29PASS   Delayed exponential ramp equals [expected array] with an element-wise tolerance of {"absoluteThreshold":0.00000429154,"relativeThreshold":0}.
    7230PASS   Delayed exponential ramp: Tail part equals [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}.
    73 FAIL < [delayed expo ramp] 1 out of 4 assertions were failed. assert_true: expected true got false
    74 FAIL # AUDIT TASK RUNNER FINISHED: 4 out of 4 tasks were failed. assert_true: expected true got false
     31PASS < [delayed expo ramp] All assertions passed. (total 4 assertions)
     32PASS # AUDIT TASK RUNNER FINISHED: 4 tasks ran successfully.
    7533
  • trunk/Source/WebCore/ChangeLog

    r267377 r267381  
     12020-09-21  Chris Dumez  <cdumez@apple.com>
     2
     3        Properly handle AudioParam.setTargetAtTime() followed by a ramp
     4        https://bugs.webkit.org/show_bug.cgi?id=216804
     5
     6        Reviewed by Darin Adler.
     7
     8        Properly handle AudioParam.setTargetAtTime() followed by a ramp:
     9        - https://www.w3.org/TR/webaudio/#dom-audioparam-settargetattime
     10        - https://www.w3.org/TR/webaudio/#dom-audioparam-linearramptovalueattime
     11        - https://www.w3.org/TR/webaudio/#dom-audioparam-exponentialramptovalueattime
     12
     13        This is a merge of the following Blink change:
     14        - https://codereview.chromium.org/1485003002
     15
     16        No new tests, rebaselined existing test.
     17
     18        * Modules/webaudio/AudioParamTimeline.cpp:
     19        (WebCore::AudioParamTimeline::valuesForTimeRangeImpl):
     20        (WebCore::AudioParamTimeline::processSetTargetFollowedByRamp):
     21        * Modules/webaudio/AudioParamTimeline.h:
     22
    1232020-09-21  Antoine Quint  <graouts@webkit.org>
    224
  • trunk/Source/WebCore/Modules/webaudio/AudioParamTimeline.cpp

    r267367 r267381  
    389389    int n = m_events.size();
    390390    for (int i = 0; i < n && writeIndex < numberOfValues; ++i) {
    391         auto& event = m_events[i].get();
     391        auto* event = &m_events[i].get();
    392392        auto* nextEvent = i < n - 1 ? &m_events[i + 1].get() : nullptr;
    393393
    394394        // Wait until we get a more recent event.
    395         if (!isEventCurrent(event, nextEvent, currentFrame, sampleRate))
     395        if (!isEventCurrent(*event, nextEvent, currentFrame, sampleRate))
    396396            continue;
    397397
    398398        auto nextEventType = nextEvent ? static_cast<ParamEvent::Type>(nextEvent->type()) : ParamEvent::LastType /* unknown */;
    399399
    400         float value1 = event.value();
    401         auto time1 = event.time();
     400        processSetTargetFollowedByRamp(i, event, nextEventType, currentFrame, sampleRate, controlRate, value);
     401
     402        float value1 = event->value();
     403        auto time1 = event->time();
    402404        float value2 = nextEvent ? nextEvent->value() : value1;
    403405        auto time2 = nextEvent ? nextEvent->time() : Seconds { endFrame * samplingPeriod + 1 };
     
    405407        ASSERT(time2 >= time1);
    406408
    407         handleCancelValues(event, nextEvent, value2, time2, nextEventType);
     409        handleCancelValues(*event, nextEvent, value2, time2, nextEventType);
    408410
    409411        auto deltaTime = time2 - time1;
     
    444446        } else {
    445447            // Handle event types not requiring looking ahead to the next event.
    446             switch (event.type()) {
     448            switch (event->type()) {
    447449            case ParamEvent::SetValue:
    448450            case ParamEvent::LinearRampToValue:
     
    451453
    452454                // Simply stay at a constant value.
    453                 value = event.value();
     455                value = event->value();
    454456                for (; writeIndex < fillToFrame; ++writeIndex)
    455457                    values[writeIndex] = value;
     
    461463                // the sample value by one sample, but only at the start of
    462464                // this CancelValues event.
    463                 if (event.hasDefaultCancelledValue())
    464                     value = event.value();
     465                if (event->hasDefaultCancelledValue())
     466                    value = event->value();
    465467                else {
    466468                    double cancelFrame = time1.value() * sampleRate;
     
    484486            case ParamEvent::SetTarget: {
    485487                // Exponential approach to target value with given time constant.
    486                 float target = event.value();
    487                 float timeConstant = event.timeConstant();
     488                float target = event->value();
     489                float timeConstant = event->timeConstant();
    488490                float discreteTimeConstant = static_cast<float>(AudioUtilities::discreteTimeConstantForSampleRate(timeConstant, controlRate));
    489491
     
    521523            }
    522524            case ParamEvent::SetValueCurve: {
    523                 float* curveData = event.curve().data();
    524                 unsigned numberOfCurvePoints = event.curve().size();
    525                 float curveEndValue = event.curveEndValue();
     525                float* curveData = event->curve().data();
     526                unsigned numberOfCurvePoints = event->curve().size();
     527                float curveEndValue = event->curveEndValue();
    526528
    527529                // Curve events have duration, so don't just use next event time.
    528                 auto duration = event.duration();
    529                 double curvePointsPerFrame = event.curvePointsPerSecond() * samplingPeriod;
     530                auto duration = event->duration();
     531                double curvePointsPerFrame = event->curvePointsPerSecond() * samplingPeriod;
    530532
    531533                if (!curveData || !numberOfCurvePoints || duration <= 0_s || sampleRate <= 0) {
     
    719721        value = values[writeIndex - 1];
    720722}
     723
     724void AudioParamTimeline::processSetTargetFollowedByRamp(int eventIndex, ParamEvent*& event, ParamEvent::Type nextEventType, size_t currentFrame, double sampleRate, double controlRate, float& value)
     725{
     726    // If the current event is SetTarget and the next event is a LinearRampToValue or ExponentialRampToValue,
     727    // special handling is needed. In this case, the linear and exponential ramp should start at wherever
     728    // the SetTarget processing has reached.
     729    if (event->type() != ParamEvent::SetTarget)
     730        return;
     731
     732    if (nextEventType != ParamEvent::LinearRampToValue && nextEventType != ParamEvent::ExponentialRampToValue)
     733        return;
     734
     735    // Replace the SetTarget with a SetValue to set the starting time and value for the ramp using the
     736    // current frame. We need to update |value| appropriately depending on whether the ramp has started
     737    // or not.
     738    //
     739    // If SetTarget starts somewhere between currentFrame - 1 and currentFrame, we directly compute the
     740    // value it would have at currentFrame. If not, we update the value from the value from currentFrame - 1.
     741    //
     742    // Can't use the condition currentFrame - 1 <= t0 * sampleRate <= currentFrame because currentFrame
     743    // is unsigned and could be 0. Instead, compute the condition this way, where f = currentFrame and
     744    // Fs = sampleRate:
     745    //
     746    //    f - 1 <= t0 * Fs <= f
     747    //    2 * f - 2 <= 2 * Fs * t0 <= 2 * f
     748    //    -2 <= 2 * Fs * t0 - 2 * f <= 0
     749    //    -1 <= 2 * Fs * t0 - 2 * f + 1 <= 1
     750    //     abs(2 * Fs * t0 - 2 * f + 1) <= 1
     751
     752    if (fabs(2 * sampleRate * event->time().value() - 2 * currentFrame + 1) <= 1) {
     753        // SetTarget is starting somewhere between currentFrame - 1 and currentFrame. Compute the value
     754        // the SetTarget would have at the currentFrame.
     755        value = event->value() + (value - event->value()) * exp(-(currentFrame / sampleRate - event->time().value()) / event->timeConstant());
     756    } else {
     757        // SetTarget has already started. Update |value| one frame because it's the value from the previous frame.
     758        float discreteTimeConstant = static_cast<float>(AudioUtilities::discreteTimeConstantForSampleRate(event->timeConstant(), controlRate));
     759        value += (event->value() - value) * discreteTimeConstant;
     760    }
     761    // Insert a SetValueEvent to mark the starting value and time.
     762    // Clear the clamp check because this doesn't need it.
     763    m_events[eventIndex] = ParamEvent::createSetValueEvent(value, Seconds { currentFrame / sampleRate });
     764
     765    // Update our pointer to the current event because we just changed it.
     766    event = &m_events[eventIndex].get();
     767}
     768
    721769
    722770float AudioParamTimeline::linearRampAtTime(Seconds t, float value1, Seconds time1, float value2, Seconds time2)
  • trunk/Source/WebCore/Modules/webaudio/AudioParamTimeline.h

    r267357 r267381  
    165165    void processLinearRamp(float* values, unsigned& writeIndex, unsigned fillToFrame, float& value, float value1, float value2, Seconds deltaTime, Seconds time1, double samplingPeriod, size_t& currentFrame);
    166166    void processSetTarget(float* values, unsigned& writeIndex, unsigned fillToFrame, float& value, float target, float discreteTimeConstant);
     167    void processSetTargetFollowedByRamp(int eventIndex, ParamEvent*&, ParamEvent::Type nextEventType, size_t currentFrame, double samplingPeriod, double controlRate, float& value);
    167168
    168169    Vector<UniqueRef<ParamEvent>> m_events;
Note: See TracChangeset for help on using the changeset viewer.