1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #ifndef AudioParamTimeline_h_
8 #define AudioParamTimeline_h_
9
10 #include "AudioEventTimeline.h"
11 #include "mozilla/ErrorResult.h"
12 #include "MediaStreamGraph.h"
13 #include "AudioSegment.h"
14
15 namespace mozilla {
16
17 namespace dom {
18
19 // This helper class is used to represent the part of the AudioParam
20 // class that gets sent to AudioNodeEngine instances. In addition to
21 // AudioEventTimeline methods, it holds a pointer to an optional
22 // MediaStream which represents the AudioNode inputs to the AudioParam.
23 // This MediaStream is managed by the AudioParam subclass on the main
24 // thread, and can only be obtained from the AudioNodeEngine instances
25 // consuming this class.
26 class AudioParamTimeline : public AudioEventTimeline {
27 typedef AudioEventTimeline BaseClass;
28
29 public:
AudioParamTimeline(float aDefaultValue)30 explicit AudioParamTimeline(float aDefaultValue) : BaseClass(aDefaultValue) {}
31
Stream()32 MediaStream* Stream() const { return mStream; }
33
HasSimpleValue()34 bool HasSimpleValue() const {
35 return BaseClass::HasSimpleValue() && !mStream;
36 }
37
38 template <class TimeType>
GetValueAtTime(TimeType aTime)39 float GetValueAtTime(TimeType aTime) {
40 return GetValueAtTime(aTime, 0);
41 }
42
43 template <typename TimeType>
InsertEvent(const AudioTimelineEvent & aEvent)44 void InsertEvent(const AudioTimelineEvent& aEvent) {
45 if (aEvent.mType == AudioTimelineEvent::Cancel) {
46 CancelScheduledValues(aEvent.template Time<TimeType>());
47 return;
48 }
49 if (aEvent.mType == AudioTimelineEvent::Stream) {
50 mStream = aEvent.mStream;
51 return;
52 }
53 if (aEvent.mType == AudioTimelineEvent::SetValue) {
54 AudioEventTimeline::SetValue(aEvent.mValue);
55 return;
56 }
57 AudioEventTimeline::InsertEvent<TimeType>(aEvent);
58 }
59
60 // Get the value of the AudioParam at time aTime + aCounter.
61 // aCounter here is an offset to aTime if we try to get the value in ticks,
62 // otherwise it should always be zero. aCounter is meant to be used when
63 template <class TimeType>
64 float GetValueAtTime(TimeType aTime, size_t aCounter);
65
66 // Get the values of the AudioParam at time aTime + (0 to aSize).
67 // aBuffer must have the correct aSize.
68 // aSize here is an offset to aTime if we try to get the value in ticks,
69 // otherwise it should always be zero. aSize is meant to be used when
70 // getting the value of an a-rate AudioParam for each tick inside an
71 // AudioNodeEngine implementation.
72 template <class TimeType>
73 void GetValuesAtTime(TimeType aTime, float* aBuffer, const size_t aSize);
74
SizeOfExcludingThis(MallocSizeOf aMallocSizeOf)75 virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const {
76 return mStream ? mStream->SizeOfIncludingThis(aMallocSizeOf) : 0;
77 }
78
SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)79 virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
80 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
81 }
82
83 private:
84 float AudioNodeInputValue(size_t aCounter) const;
85
86 protected:
87 // This is created lazily when needed.
88 RefPtr<MediaStream> mStream;
89 };
90
91 template <>
GetValueAtTime(double aTime,size_t aCounter)92 inline float AudioParamTimeline::GetValueAtTime(double aTime, size_t aCounter) {
93 MOZ_ASSERT(!aCounter);
94
95 // Getting an AudioParam value on an AudioNode does not consider input from
96 // other AudioNodes, which is managed only on the graph thread.
97 return BaseClass::GetValueAtTime(aTime);
98 }
99
100 template <>
GetValueAtTime(int64_t aTime,size_t aCounter)101 inline float AudioParamTimeline::GetValueAtTime(int64_t aTime,
102 size_t aCounter) {
103 MOZ_ASSERT(aCounter < WEBAUDIO_BLOCK_SIZE);
104 MOZ_ASSERT(!aCounter || !HasSimpleValue());
105
106 // Mix the value of the AudioParam itself with that of the AudioNode inputs.
107 return BaseClass::GetValueAtTime(static_cast<int64_t>(aTime + aCounter)) +
108 (mStream ? AudioNodeInputValue(aCounter) : 0.0f);
109 }
110
111 template <>
GetValuesAtTime(double aTime,float * aBuffer,const size_t aSize)112 inline void AudioParamTimeline::GetValuesAtTime(double aTime, float* aBuffer,
113 const size_t aSize) {
114 MOZ_ASSERT(aBuffer);
115 MOZ_ASSERT(aSize == 1);
116
117 // Getting an AudioParam value on an AudioNode does not consider input from
118 // other AudioNodes, which is managed only on the graph thread.
119 *aBuffer = BaseClass::GetValueAtTime(aTime);
120 }
121
122 template <>
GetValuesAtTime(int64_t aTime,float * aBuffer,const size_t aSize)123 inline void AudioParamTimeline::GetValuesAtTime(int64_t aTime, float* aBuffer,
124 const size_t aSize) {
125 MOZ_ASSERT(aBuffer);
126 MOZ_ASSERT(aSize <= WEBAUDIO_BLOCK_SIZE);
127 MOZ_ASSERT(aSize == 1 || !HasSimpleValue());
128
129 // Mix the value of the AudioParam itself with that of the AudioNode inputs.
130 BaseClass::GetValuesAtTime(aTime, aBuffer, aSize);
131 if (mStream) {
132 for (size_t i = 0; i < aSize; ++i) {
133 aBuffer[i] += AudioNodeInputValue(i);
134 }
135 }
136 }
137
138 } // namespace dom
139 } // namespace mozilla
140
141 #endif
142