• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010, Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24 
25 #ifndef PannerNode_h
26 #define PannerNode_h
27 
28 #include "platform/audio/AudioBus.h"
29 #include "platform/audio/Cone.h"
30 #include "platform/audio/Distance.h"
31 #include "platform/audio/Panner.h"
32 #include "modules/webaudio/AudioListener.h"
33 #include "modules/webaudio/AudioNode.h"
34 #include "platform/geometry/FloatPoint3D.h"
35 #include "wtf/HashMap.h"
36 
37 namespace blink {
38 
39 // PannerNode is an AudioNode with one input and one output.
40 // It positions a sound in 3D space, with the exact effect dependent on the panning model.
41 // It has a position and an orientation in 3D space which is relative to the position and orientation of the context's AudioListener.
42 // A distance effect will attenuate the gain as the position moves away from the listener.
43 // A cone effect will attenuate the gain as the orientation moves away from the listener.
44 // All of these effects follow the OpenAL specification very closely.
45 
46 class PannerNode FINAL : public AudioNode {
47     DEFINE_WRAPPERTYPEINFO();
48 public:
49     // These enums are used to distinguish what cached values of panner are dirty.
50     enum {
51         AzimuthElevationDirty = 0x1,
52         DistanceConeGainDirty = 0x2,
53         DopplerRateDirty = 0x4,
54     };
55 
create(AudioContext * context,float sampleRate)56     static PannerNode* create(AudioContext* context, float sampleRate)
57     {
58         return adoptRefCountedGarbageCollectedWillBeNoop(new PannerNode(context, sampleRate));
59     }
60 
61     virtual ~PannerNode();
62 
63     // AudioNode
64     virtual void dispose() OVERRIDE;
65     virtual void process(size_t framesToProcess) OVERRIDE;
66     virtual void pullInputs(size_t framesToProcess) OVERRIDE;
67     virtual void initialize() OVERRIDE;
68     virtual void uninitialize() OVERRIDE;
69 
70     // Panning model
71     String panningModel() const;
72     void setPanningModel(const String&);
73 
74     // Position, orientation and velocity
75     void setPosition(float x, float y, float z);
76     void setOrientation(float x, float y, float z);
77     void setVelocity(float x, float y, float z);
78 
79     // Distance parameters
80     String distanceModel() const;
81     void setDistanceModel(const String&);
82 
refDistance()83     double refDistance() { return m_distanceEffect.refDistance(); }
84     void setRefDistance(double);
85 
maxDistance()86     double maxDistance() { return m_distanceEffect.maxDistance(); }
87     void setMaxDistance(double);
88 
rolloffFactor()89     double rolloffFactor() { return m_distanceEffect.rolloffFactor(); }
90     void setRolloffFactor(double);
91 
92     // Sound cones - angles in degrees
coneInnerAngle()93     double coneInnerAngle() const { return m_coneEffect.innerAngle(); }
94     void setConeInnerAngle(double);
95 
coneOuterAngle()96     double coneOuterAngle() const { return m_coneEffect.outerAngle(); }
97     void setConeOuterAngle(double);
98 
coneOuterGain()99     double coneOuterGain() const { return m_coneEffect.outerGain(); }
100     void setConeOuterGain(double);
101 
102     void markPannerAsDirty(unsigned);
103 
104     // It must be called on audio thread, currently called only process() in AudioBufferSourceNode.
105     double dopplerRate();
106 
tailTime()107     virtual double tailTime() const OVERRIDE { return m_panner ? m_panner->tailTime() : 0; }
latencyTime()108     virtual double latencyTime() const OVERRIDE { return m_panner ? m_panner->latencyTime() : 0; }
109 
110     virtual void trace(Visitor*) OVERRIDE;
111 
112 private:
113     PannerNode(AudioContext*, float sampleRate);
114 
115     // AudioContext's listener
116     AudioListener* listener();
117 
118     bool setPanningModel(unsigned); // Returns true on success.
119     bool setDistanceModel(unsigned); // Returns true on success.
120 
121     void calculateAzimuthElevation(double* outAzimuth, double* outElevation);
122     float calculateDistanceConeGain(); // Returns the combined distance and cone gain attenuation.
123     double calculateDopplerRate();
124 
125     void azimuthElevation(double* outAzimuth, double* outElevation);
126     float distanceConeGain();
127 
isAzimuthElevationDirty()128     bool isAzimuthElevationDirty() const { return m_isAzimuthElevationDirty; }
isDistanceConeGainDirty()129     bool isDistanceConeGainDirty() const { return m_isDistanceConeGainDirty; }
isDopplerRateDirty()130     bool isDopplerRateDirty() const { return m_isDopplerRateDirty; }
131 
132     // Notifies any AudioBufferSourceNodes connected to us either directly or indirectly about our existence.
133     // This is in order to handle the pitch change necessary for the doppler shift.
134     void notifyAudioSourcesConnectedToNode(AudioNode*, HashMap<AudioNode*, bool> &visitedNodes);
135 
136     Member<Panner> m_panner;
137     unsigned m_panningModel;
138     unsigned m_distanceModel;
139 
140     // Current source location information
141     FloatPoint3D m_position;
142     FloatPoint3D m_orientation;
143     FloatPoint3D m_velocity;
144 
145     bool m_isAzimuthElevationDirty;
146     bool m_isDistanceConeGainDirty;
147     bool m_isDopplerRateDirty;
148 
149     // Gain
150     DistanceEffect m_distanceEffect;
151     ConeEffect m_coneEffect;
152     float m_lastGain;
153 
154     // Cached values
155     double m_cachedAzimuth;
156     double m_cachedElevation;
157     float m_cachedDistanceConeGain;
158     double m_cachedDopplerRate;
159 
160     // AudioContext's connection count
161     unsigned m_connectionCount;
162 
163     // Synchronize process() with setting of the panning model, source's location information, listener, distance parameters and sound cones.
164     mutable Mutex m_processLock;
165 };
166 
167 } // namespace blink
168 
169 #endif // PannerNode_h
170