AudioParam.h (7420B)
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 AudioParam_h_ 8 #define AudioParam_h_ 9 10 #include "AudioNode.h" 11 #include "AudioParamTimeline.h" 12 #include "WebAudioUtils.h" 13 #include "js/TypeDecls.h" 14 #include "mozilla/ErrorResult.h" 15 #include "mozilla/dom/TypedArray.h" 16 #include "nsCycleCollectionParticipant.h" 17 #include "nsWrapperCache.h" 18 19 namespace mozilla::dom { 20 21 class AudioParam final : public nsWrapperCache, public AudioParamTimeline { 22 virtual ~AudioParam(); 23 24 public: 25 AudioParam(AudioNode* aNode, uint32_t aIndex, const nsAString& aName, 26 float aDefaultValue, 27 float aMinValue = std::numeric_limits<float>::lowest(), 28 float aMaxValue = std::numeric_limits<float>::max()); 29 30 NS_IMETHOD_(MozExternalRefCountType) AddRef(void); 31 NS_IMETHOD_(MozExternalRefCountType) Release(void); 32 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(AudioParam) 33 34 AudioContext* GetParentObject() const { return mNode->Context(); } 35 36 JSObject* WrapObject(JSContext* aCx, 37 JS::Handle<JSObject*> aGivenProto) override; 38 39 float Value() { 40 return AudioParamTimeline::GetValueAtTime<double>( 41 GetParentObject()->CurrentTime()); 42 } 43 44 // We override SetValueCurveAtTime to convert the Float32Array to the wrapper 45 // object. 46 AudioParam* SetValueCurveAtTime(const nsTArray<float>& aValues, 47 double aStartTime, double aDuration, 48 ErrorResult& aRv) { 49 if (!WebAudioUtils::IsTimeValid(aStartTime)) { 50 aRv.ThrowRangeError<MSG_INVALID_AUDIOPARAM_METHOD_START_TIME_ERROR>(); 51 return this; 52 } 53 aStartTime = std::max(aStartTime, GetParentObject()->CurrentTime()); 54 AudioParamEvent event(AudioTimelineEvent::SetValueCurve, aValues, 55 aStartTime, aDuration); 56 ValidateAndInsertEvent(event, aRv); 57 return this; 58 } 59 60 // Intended for use in AudioNode creation, when the setter should not throw. 61 void SetInitialValue(float aValue) { 62 IgnoredErrorResult rv; 63 SetValue(aValue, rv); 64 } 65 66 void SetValue(float aValue, ErrorResult& aRv) { 67 SetValueAtTime(aValue, GetParentObject()->CurrentTime(), aRv); 68 } 69 70 AudioParam* SetValueAtTime(float aValue, double aStartTime, 71 ErrorResult& aRv) { 72 if (!WebAudioUtils::IsTimeValid(aStartTime)) { 73 aRv.ThrowRangeError<MSG_INVALID_AUDIOPARAM_METHOD_START_TIME_ERROR>(); 74 return this; 75 } 76 aStartTime = std::max(aStartTime, GetParentObject()->CurrentTime()); 77 AudioParamEvent event(AudioTimelineEvent::SetValueAtTime, aStartTime, 78 aValue); 79 ValidateAndInsertEvent(event, aRv); 80 return this; 81 } 82 83 AudioParam* LinearRampToValueAtTime(float aValue, double aEndTime, 84 ErrorResult& aRv) { 85 if (!WebAudioUtils::IsTimeValid(aEndTime)) { 86 aRv.ThrowRangeError<MSG_INVALID_AUDIOPARAM_METHOD_END_TIME_ERROR>(); 87 return this; 88 } 89 aEndTime = std::max(aEndTime, GetParentObject()->CurrentTime()); 90 AudioParamEvent event(AudioTimelineEvent::LinearRamp, aEndTime, aValue); 91 ValidateAndInsertEvent(event, aRv); 92 return this; 93 } 94 95 AudioParam* ExponentialRampToValueAtTime(float aValue, double aEndTime, 96 ErrorResult& aRv) { 97 if (!WebAudioUtils::IsTimeValid(aEndTime)) { 98 aRv.ThrowRangeError<MSG_INVALID_AUDIOPARAM_METHOD_END_TIME_ERROR>(); 99 return this; 100 } 101 aEndTime = std::max(aEndTime, GetParentObject()->CurrentTime()); 102 AudioParamEvent event(AudioTimelineEvent::ExponentialRamp, aEndTime, 103 aValue); 104 ValidateAndInsertEvent(event, aRv); 105 return this; 106 } 107 108 AudioParam* SetTargetAtTime(float aTarget, double aStartTime, 109 double aTimeConstant, ErrorResult& aRv) { 110 if (!WebAudioUtils::IsTimeValid(aStartTime) || 111 !WebAudioUtils::IsTimeValid(aTimeConstant)) { 112 aRv.ThrowRangeError<MSG_INVALID_AUDIOPARAM_METHOD_START_TIME_ERROR>(); 113 return this; 114 } 115 aStartTime = std::max(aStartTime, GetParentObject()->CurrentTime()); 116 AudioParamEvent event(AudioTimelineEvent::SetTarget, aStartTime, aTarget, 117 aTimeConstant); 118 ValidateAndInsertEvent(event, aRv); 119 return this; 120 } 121 122 AudioParam* CancelScheduledValues(double aStartTime, ErrorResult& aRv) { 123 if (!WebAudioUtils::IsTimeValid(aStartTime)) { 124 aRv.ThrowRangeError<MSG_INVALID_AUDIOPARAM_METHOD_START_TIME_ERROR>(); 125 return this; 126 } 127 128 aStartTime = std::max(aStartTime, GetParentObject()->CurrentTime()); 129 130 // Remove some events on the main thread copy. 131 AudioEventTimeline::CancelScheduledValues(aStartTime); 132 133 AudioParamEvent event(AudioTimelineEvent::Cancel, aStartTime, 0.0f); 134 135 SendEventToEngine(event); 136 137 return this; 138 } 139 140 uint32_t ParentNodeId() { return mNode->Id(); } 141 142 void GetName(nsAString& aName) { aName.Assign(mName); } 143 144 float DefaultValue() const { return mDefaultValue; } 145 146 float MinValue() const { return mMinValue; } 147 148 float MaxValue() const { return mMaxValue; } 149 150 bool IsTrackSuspended() const { 151 return mTrack ? mTrack->IsSuspended() : false; 152 } 153 154 const nsTArray<AudioNode::InputNode>& InputNodes() const { 155 return mInputNodes; 156 } 157 158 void RemoveInputNode(uint32_t aIndex) { mInputNodes.RemoveElementAt(aIndex); } 159 160 AudioNode::InputNode* AppendInputNode() { 161 return mInputNodes.AppendElement(); 162 } 163 164 // May create the track if it doesn't exist 165 mozilla::MediaTrack* Track(); 166 167 // Return nullptr if track doesn't exist. 168 mozilla::MediaTrack* GetTrack() const; 169 170 size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override { 171 size_t amount = AudioParamTimeline::SizeOfExcludingThis(aMallocSizeOf); 172 // Not owned: 173 // - mNode 174 175 // Just count the array, actual nodes are counted in mNode. 176 amount += mInputNodes.ShallowSizeOfExcludingThis(aMallocSizeOf); 177 178 if (mNodeTrackPort) { 179 amount += mNodeTrackPort->SizeOfIncludingThis(aMallocSizeOf); 180 } 181 182 return amount; 183 } 184 185 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override { 186 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); 187 } 188 189 private: 190 void ValidateAndInsertEvent(const AudioParamEvent& aEvent, ErrorResult& aRv) { 191 if (!ValidateEvent(aEvent, aRv)) { 192 return; 193 } 194 195 AudioEventTimeline::InsertEvent<double>(aEvent); 196 197 SendEventToEngine(aEvent); 198 199 CleanupOldEvents(); 200 } 201 202 void CleanupOldEvents(); 203 204 void SendEventToEngine(const AudioParamEvent& aEvent); 205 206 void DisconnectFromGraphAndDestroyTrack(); 207 208 nsCycleCollectingAutoRefCnt mRefCnt; 209 NS_DECL_OWNINGTHREAD 210 RefPtr<AudioNode> mNode; 211 // For every InputNode, there is a corresponding entry in mOutputParams of the 212 // InputNode's mInputNode. 213 nsTArray<AudioNode::InputNode> mInputNodes; 214 const nsString mName; 215 // The input port used to connect the AudioParam's track to its node's track 216 RefPtr<MediaInputPort> mNodeTrackPort; 217 const uint32_t mIndex; 218 const float mDefaultValue; 219 const float mMinValue; 220 const float mMaxValue; 221 }; 222 223 } // namespace mozilla::dom 224 225 #endif