File: AudioParamTimeline.h

package info (click to toggle)
webkit2gtk 2.48.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 429,764 kB
  • sloc: cpp: 3,697,587; javascript: 194,444; ansic: 169,997; python: 46,499; asm: 19,295; ruby: 18,528; perl: 16,602; xml: 4,650; yacc: 2,360; sh: 2,098; java: 1,993; lex: 1,327; pascal: 366; makefile: 298
file content (215 lines) | stat: -rw-r--r-- 10,209 bytes parent folder | download | duplicates (6)
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