| /* |
| * Copyright (C) 2010, 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. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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 |
| |
| #if ENABLE(WEB_AUDIO) |
| |
| #include "AudioContext.h" |
| #include "AudioListener.h" |
| #include "AudioNode.h" |
| #include "AudioParam.h" |
| #include "Cone.h" |
| #include "Distance.h" |
| #include "FloatPoint3D.h" |
| #include "Panner.h" |
| #include "PannerOptions.h" |
| #include <memory> |
| #include <wtf/HashSet.h> |
| #include <wtf/Lock.h> |
| |
| namespace WebCore { |
| |
| class HRTFDatabaseLoader; |
| class BaseAudioContext; |
| |
| // PannerNode is an AudioNode with one input and one output. |
| // It positions a sound in 3D space, with the exact effect dependent on the panning model. |
| // It has a position and an orientation in 3D space which is relative to the position and orientation of the context's AudioListener. |
| // A distance effect will attenuate the gain as the position moves away from the listener. |
| // A cone effect will attenuate the gain as the orientation moves away from the listener. |
| // All of these effects follow the OpenAL specification very closely. |
| |
| class PannerNode final : public AudioNode { |
| WTF_MAKE_ISO_ALLOCATED(PannerNode); |
| public: |
| static ExceptionOr<Ref<PannerNode>> create(BaseAudioContext&, const PannerOptions& = { }); |
| |
| virtual ~PannerNode(); |
| |
| // AudioNode |
| void process(size_t framesToProcess) override; |
| void processOnlyAudioParams(size_t framesToProcess) final; |
| |
| // Listener |
| AudioListener& listener(); |
| |
| // Panning model |
| PanningModelType panningModelForBindings() const WTF_IGNORES_THREAD_SAFETY_ANALYSIS { ASSERT(isMainThread()); return m_panningModel; } |
| void setPanningModelForBindings(PanningModelType); |
| |
| // Position |
| ExceptionOr<void> setPosition(float x, float y, float z); |
| AudioParam& positionX() WTF_IGNORES_THREAD_SAFETY_ANALYSIS { ASSERT(isMainThread()); return m_positionX.get(); } |
| AudioParam& positionY() WTF_IGNORES_THREAD_SAFETY_ANALYSIS { ASSERT(isMainThread()); return m_positionY.get(); } |
| AudioParam& positionZ() WTF_IGNORES_THREAD_SAFETY_ANALYSIS { ASSERT(isMainThread()); return m_positionZ.get(); } |
| |
| // Orientation |
| ExceptionOr<void> setOrientation(float x, float y, float z); |
| AudioParam& orientationX() WTF_IGNORES_THREAD_SAFETY_ANALYSIS { ASSERT(isMainThread()); return m_orientationX.get(); } |
| AudioParam& orientationY() WTF_IGNORES_THREAD_SAFETY_ANALYSIS { ASSERT(isMainThread()); return m_orientationY.get(); } |
| AudioParam& orientationZ() WTF_IGNORES_THREAD_SAFETY_ANALYSIS { ASSERT(isMainThread()); return m_orientationZ.get(); } |
| |
| // Distance parameters |
| DistanceModelType distanceModelForBindings() const; |
| void setDistanceModelForBindings(DistanceModelType); |
| |
| double refDistanceForBindings() const WTF_IGNORES_THREAD_SAFETY_ANALYSIS { ASSERT(isMainThread()); return m_distanceEffect.refDistance(); } |
| ExceptionOr<void> setRefDistanceForBindings(double); |
| |
| double maxDistanceForBindings() const WTF_IGNORES_THREAD_SAFETY_ANALYSIS { ASSERT(isMainThread()); return m_distanceEffect.maxDistance(); } |
| ExceptionOr<void> setMaxDistanceForBindings(double); |
| |
| double rolloffFactorForBindings() const WTF_IGNORES_THREAD_SAFETY_ANALYSIS { ASSERT(isMainThread()); return m_distanceEffect.rolloffFactor(); } |
| ExceptionOr<void> setRolloffFactorForBindings(double); |
| |
| // Sound cones - angles in degrees |
| double coneInnerAngleForBindings() const WTF_IGNORES_THREAD_SAFETY_ANALYSIS { ASSERT(isMainThread()); return m_coneEffect.innerAngle(); } |
| void setConeInnerAngleForBindings(double); |
| |
| double coneOuterAngleForBindings() const WTF_IGNORES_THREAD_SAFETY_ANALYSIS { ASSERT(isMainThread()); return m_coneEffect.outerAngle(); } |
| void setConeOuterAngleForBindings(double); |
| |
| double coneOuterGainForBindings() const WTF_IGNORES_THREAD_SAFETY_ANALYSIS { ASSERT(isMainThread()); return m_coneEffect.outerGain(); } |
| ExceptionOr<void> setConeOuterGainForBindings(double); |
| |
| ExceptionOr<void> setChannelCount(unsigned) final; |
| ExceptionOr<void> setChannelCountMode(ChannelCountMode) final; |
| |
| double tailTime() const final; |
| double latencyTime() const final; |
| |
| private: |
| PannerNode(BaseAudioContext&, const PannerOptions&); |
| |
| struct AzimuthElevation { |
| double azimuth { 0. }; |
| double elevation { 0. }; |
| }; |
| static AzimuthElevation calculateAzimuthElevation(const FloatPoint3D& position, const FloatPoint3D& listenerPosition, const FloatPoint3D& listenerForward, const FloatPoint3D& listenerUp); |
| static float calculateDistanceConeGain(const FloatPoint3D& position, const FloatPoint3D& orientation, const FloatPoint3D& listenerPosition, const DistanceEffect&, const ConeEffect&); |
| |
| // Returns the combined distance and cone gain attenuation. |
| float distanceConeGain() WTF_REQUIRES_LOCK(m_processLock); |
| |
| bool requiresTailProcessing() const final; |
| |
| void invalidateCachedPropertiesIfNecessary() WTF_REQUIRES_LOCK(m_processLock); |
| |
| const AzimuthElevation& azimuthElevation() WTF_REQUIRES_LOCK(m_processLock); |
| void processSampleAccurateValues(AudioBus* destination, const AudioBus* source, size_t framesToProcess) WTF_REQUIRES_LOCK(m_processLock); |
| bool hasSampleAccurateValues() const WTF_REQUIRES_LOCK(m_processLock); |
| bool shouldUseARate() const WTF_REQUIRES_LOCK(m_processLock); |
| |
| FloatPoint3D position() const WTF_REQUIRES_LOCK(m_processLock); |
| FloatPoint3D orientation() const WTF_REQUIRES_LOCK(m_processLock); |
| |
| Ref<HRTFDatabaseLoader> m_hrtfDatabaseLoader; |
| PanningModelType m_panningModel WTF_GUARDED_BY_LOCK(m_processLock); |
| std::unique_ptr<Panner> m_panner WTF_GUARDED_BY_LOCK(m_processLock); |
| |
| // Gain |
| DistanceEffect m_distanceEffect WTF_GUARDED_BY_LOCK(m_processLock); |
| ConeEffect m_coneEffect WTF_GUARDED_BY_LOCK(m_processLock); |
| |
| Ref<AudioParam> m_positionX WTF_GUARDED_BY_LOCK(m_processLock); |
| Ref<AudioParam> m_positionY WTF_GUARDED_BY_LOCK(m_processLock); |
| Ref<AudioParam> m_positionZ WTF_GUARDED_BY_LOCK(m_processLock); |
| |
| Ref<AudioParam> m_orientationX WTF_GUARDED_BY_LOCK(m_processLock); |
| Ref<AudioParam> m_orientationY WTF_GUARDED_BY_LOCK(m_processLock); |
| Ref<AudioParam> m_orientationZ WTF_GUARDED_BY_LOCK(m_processLock); |
| |
| mutable std::optional<AzimuthElevation> m_cachedAzimuthElevation WTF_GUARDED_BY_LOCK(m_processLock); |
| mutable std::optional<float> m_cachedConeGain WTF_GUARDED_BY_LOCK(m_processLock); |
| FloatPoint3D m_lastPosition WTF_GUARDED_BY_LOCK(m_processLock); |
| FloatPoint3D m_lastOrientation WTF_GUARDED_BY_LOCK(m_processLock); |
| |
| // Synchronize process() with setting of the panning model, source's location |
| // information, listener, distance parameters and sound cones. |
| mutable Lock m_processLock; |
| }; |
| |
| } // namespace WebCore |
| |
| #endif |