OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2010, Google Inc. All rights reserved. | 2 * Copyright (C) 2010, Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 13 matching lines...) Expand all Loading... | |
24 | 24 |
25 #include "config.h" | 25 #include "config.h" |
26 | 26 |
27 #if ENABLE(WEB_AUDIO) | 27 #if ENABLE(WEB_AUDIO) |
28 | 28 |
29 #include "modules/webaudio/PannerNode.h" | 29 #include "modules/webaudio/PannerNode.h" |
30 | 30 |
31 #include "core/dom/ExecutionContext.h" | 31 #include "core/dom/ExecutionContext.h" |
32 #include "platform/audio/HRTFPanner.h" | 32 #include "platform/audio/HRTFPanner.h" |
33 #include "modules/webaudio/AudioBufferSourceNode.h" | 33 #include "modules/webaudio/AudioBufferSourceNode.h" |
34 #include "modules/webaudio/AudioContext.h" | |
35 #include "modules/webaudio/AudioNodeInput.h" | 34 #include "modules/webaudio/AudioNodeInput.h" |
36 #include "modules/webaudio/AudioNodeOutput.h" | 35 #include "modules/webaudio/AudioNodeOutput.h" |
37 #include "wtf/MathExtras.h" | 36 #include "wtf/MathExtras.h" |
38 | 37 |
39 using namespace std; | 38 using namespace std; |
40 | 39 |
41 namespace WebCore { | 40 namespace WebCore { |
42 | 41 |
43 static void fixNANs(double &x) | 42 static void fixNANs(double &x) |
44 { | 43 { |
45 if (std::isnan(x) || std::isinf(x)) | 44 if (std::isnan(x) || std::isinf(x)) |
46 x = 0.0; | 45 x = 0.0; |
47 } | 46 } |
48 | 47 |
49 PannerNode::PannerNode(AudioContext* context, float sampleRate) | 48 PannerNode::PannerNode(AudioContext* context, float sampleRate) |
50 : AudioNode(context, sampleRate) | 49 : AudioNode(context, sampleRate) |
51 , m_panningModel(Panner::PanningModelHRTF) | 50 , m_panningModel(Panner::PanningModelHRTF) |
52 , m_distanceModel(DistanceEffect::ModelInverse) | 51 , m_distanceModel(DistanceEffect::ModelInverse) |
53 , m_position(0, 0, 0) | 52 , m_position(0, 0, 0) |
54 , m_orientation(1, 0, 0) | 53 , m_orientation(1, 0, 0) |
55 , m_velocity(0, 0, 0) | 54 , m_velocity(0, 0, 0) |
56 , m_cachedPosition(0, 0, 0) | 55 , m_isAzimuthElevationDirty(true) |
57 , m_cachedOrientation(1, 0, 0) | 56 , m_isDistanceConeGainDirty(true) |
58 , m_cachedVelocity(0, 0, 0) | 57 , m_isDopplerRateDirty(true) |
59 , m_lastGain(-1.0) | 58 , m_lastGain(-1.0) |
60 , m_cachedAzimuth(0) | 59 , m_cachedAzimuth(0) |
61 , m_cachedElevation(0) | 60 , m_cachedElevation(0) |
62 , m_cachedDistanceConeGain(1.0f) | 61 , m_cachedDistanceConeGain(1.0f) |
63 , m_cachedDopplerRate(1) | 62 , m_cachedDopplerRate(1) |
64 , m_connectionCount(0) | 63 , m_connectionCount(0) |
65 { | 64 { |
66 // Load the HRTF database asynchronously so we don't block the Javascript th read while creating the HRTF database. | 65 // Load the HRTF database asynchronously so we don't block the Javascript th read while creating the HRTF database. |
67 // The HRTF panner will return zeroes until the database is loaded. | 66 // The HRTF panner will return zeroes until the database is loaded. |
68 m_hrtfDatabaseLoader = HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNece ssary(context->sampleRate()); | 67 m_hrtfDatabaseLoader = HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNece ssary(context->sampleRate()); |
69 | 68 |
70 ScriptWrappable::init(this); | 69 ScriptWrappable::init(this); |
71 addInput(adoptPtr(new AudioNodeInput(this))); | 70 addInput(adoptPtr(new AudioNodeInput(this))); |
72 addOutput(adoptPtr(new AudioNodeOutput(this, 2))); | 71 addOutput(adoptPtr(new AudioNodeOutput(this, 2))); |
73 | 72 |
74 // Node-specific default mixing rules. | 73 // Node-specific default mixing rules. |
75 m_channelCount = 2; | 74 m_channelCount = 2; |
76 m_channelCountMode = ClampedMax; | 75 m_channelCountMode = ClampedMax; |
77 m_channelInterpretation = AudioBus::Speakers; | 76 m_channelInterpretation = AudioBus::Speakers; |
78 | 77 |
79 m_cachedListener = AudioListener::create(); | |
80 | |
81 setNodeType(NodeTypePanner); | 78 setNodeType(NodeTypePanner); |
82 | 79 |
83 initialize(); | 80 initialize(); |
84 } | 81 } |
85 | 82 |
86 PannerNode::~PannerNode() | 83 PannerNode::~PannerNode() |
87 { | 84 { |
88 uninitialize(); | 85 uninitialize(); |
89 } | 86 } |
90 | 87 |
(...skipping 25 matching lines...) Expand all Loading... | |
116 } | 113 } |
117 | 114 |
118 AudioBus* source = input(0)->bus(); | 115 AudioBus* source = input(0)->bus(); |
119 if (!source) { | 116 if (!source) { |
120 destination->zero(); | 117 destination->zero(); |
121 return; | 118 return; |
122 } | 119 } |
123 | 120 |
124 // The audio thread can't block on this lock, so we call tryLock() instead. | 121 // The audio thread can't block on this lock, so we call tryLock() instead. |
125 MutexTryLocker tryLocker(m_processLock); | 122 MutexTryLocker tryLocker(m_processLock); |
126 if (tryLocker.locked()) { | 123 MutexTryLocker tryListenerLocker(listener()->listenerLock()); |
KhNo
2014/04/14 11:23:30
It is required to lock context's listener.
| |
124 | |
125 if (tryLocker.locked() && tryListenerLocker.locked()) { | |
127 // HRTFDatabase should be loaded before proceeding for offline audio con text when the panning model is HRTF. | 126 // HRTFDatabase should be loaded before proceeding for offline audio con text when the panning model is HRTF. |
128 if (m_panningModel == HRTF && !m_hrtfDatabaseLoader->isLoaded()) { | 127 if (m_panningModel == HRTF && !m_hrtfDatabaseLoader->isLoaded()) { |
129 if (context()->isOfflineContext()) { | 128 if (context()->isOfflineContext()) { |
130 m_hrtfDatabaseLoader->waitForLoaderThreadCompletion(); | 129 m_hrtfDatabaseLoader->waitForLoaderThreadCompletion(); |
131 } else { | 130 } else { |
132 destination->zero(); | 131 destination->zero(); |
133 return; | 132 return; |
134 } | 133 } |
135 } | 134 } |
136 | 135 |
137 // Apply the panning effect. | 136 // Apply the panning effect. |
138 double azimuth; | 137 double azimuth; |
139 double elevation; | 138 double elevation; |
140 azimuthElevation(&azimuth, &elevation); | 139 azimuthElevation(&azimuth, &elevation); |
141 | 140 |
142 m_panner->pan(azimuth, elevation, source, destination, framesToProcess); | 141 m_panner->pan(azimuth, elevation, source, destination, framesToProcess); |
143 | 142 |
144 // Get the distance and cone gain. | 143 // Get the distance and cone gain. |
145 float totalGain = distanceConeGain(); | 144 float totalGain = distanceConeGain(); |
146 | 145 |
147 // Snap to desired gain at the beginning. | 146 // Snap to desired gain at the beginning. |
148 if (m_lastGain == -1.0) | 147 if (m_lastGain == -1.0) |
149 m_lastGain = totalGain; | 148 m_lastGain = totalGain; |
150 | 149 |
151 // Apply gain in-place with de-zippering. | 150 // Apply gain in-place with de-zippering. |
152 destination->copyWithGainFrom(*destination, &m_lastGain, totalGain); | 151 destination->copyWithGainFrom(*destination, &m_lastGain, totalGain); |
153 | |
154 // Update the cached listener in case listener has moved. | |
155 updateCachedListener(); | |
156 // Now update the cached source location in case the source has changed. | |
157 updateCachedSourceLocationInfo(); | |
158 } else { | 152 } else { |
159 // Too bad - The tryLock() failed. | 153 // Too bad - The tryLock() failed. |
160 // We must be in the middle of changing the panning model, the distance model, or the source's location information. | 154 // We must be in the middle of changing the panning model, source's loca tion information, listener, distance parameters and sound cones. |
161 destination->zero(); | 155 destination->zero(); |
162 } | 156 } |
163 } | 157 } |
164 | 158 |
165 void PannerNode::initialize() | 159 void PannerNode::initialize() |
166 { | 160 { |
167 if (isInitialized()) | 161 if (isInitialized()) |
168 return; | 162 return; |
169 | 163 |
170 m_panner = Panner::create(m_panningModel, sampleRate(), m_hrtfDatabaseLoader .get()); | 164 m_panner = Panner::create(m_panningModel, sampleRate(), m_hrtfDatabaseLoader .get()); |
165 listener()->addPanner(this); | |
171 | 166 |
172 AudioNode::initialize(); | 167 AudioNode::initialize(); |
173 } | 168 } |
174 | 169 |
175 void PannerNode::uninitialize() | 170 void PannerNode::uninitialize() |
176 { | 171 { |
177 if (!isInitialized()) | 172 if (!isInitialized()) |
178 return; | 173 return; |
179 | 174 |
180 m_panner.clear(); | 175 m_panner.clear(); |
176 listener()->removePanner(this); | |
177 | |
181 AudioNode::uninitialize(); | 178 AudioNode::uninitialize(); |
182 } | 179 } |
183 | 180 |
184 AudioListener* PannerNode::listener() | |
185 { | |
186 return context()->listener(); | |
187 } | |
188 | |
189 String PannerNode::panningModel() const | 181 String PannerNode::panningModel() const |
190 { | 182 { |
191 switch (m_panningModel) { | 183 switch (m_panningModel) { |
192 case EQUALPOWER: | 184 case EqualPower: |
193 return "equalpower"; | 185 return "equalpower"; |
194 case HRTF: | 186 case HRTF: |
195 return "HRTF"; | 187 return "HRTF"; |
196 default: | 188 default: |
197 ASSERT_NOT_REACHED(); | 189 ASSERT_NOT_REACHED(); |
198 return "HRTF"; | 190 return "HRTF"; |
199 } | 191 } |
200 } | 192 } |
201 | 193 |
202 void PannerNode::setPanningModel(const String& model) | 194 void PannerNode::setPanningModel(const String& model) |
203 { | 195 { |
204 if (model == "equalpower") | 196 if (model == "equalpower") |
205 setPanningModel(EQUALPOWER); | 197 setPanningModel(EqualPower); |
206 else if (model == "HRTF") | 198 else if (model == "HRTF") |
207 setPanningModel(HRTF); | 199 setPanningModel(HRTF); |
208 } | 200 } |
209 | 201 |
210 bool PannerNode::setPanningModel(unsigned model) | 202 bool PannerNode::setPanningModel(unsigned model) |
211 { | 203 { |
212 switch (model) { | 204 switch (model) { |
213 case EQUALPOWER: | 205 case EqualPower: |
214 case HRTF: | 206 case HRTF: |
215 if (!m_panner.get() || model != m_panningModel) { | 207 if (!m_panner.get() || model != m_panningModel) { |
216 // This synchronizes with process(). | 208 // This synchronizes with process(). |
217 MutexLocker processLocker(m_processLock); | 209 MutexLocker processLocker(m_processLock); |
218 | |
219 OwnPtr<Panner> newPanner = Panner::create(model, sampleRate(), m_hrt fDatabaseLoader.get()); | 210 OwnPtr<Panner> newPanner = Panner::create(model, sampleRate(), m_hrt fDatabaseLoader.get()); |
220 m_panner = newPanner.release(); | 211 m_panner = newPanner.release(); |
221 m_panningModel = model; | 212 m_panningModel = model; |
222 } | 213 } |
223 break; | 214 break; |
224 default: | 215 default: |
225 return false; | 216 return false; |
226 } | 217 } |
227 | 218 |
228 return true; | 219 return true; |
229 } | 220 } |
230 | 221 |
231 void PannerNode::setPosition(float x, float y, float z) | |
232 { | |
233 FloatPoint3D position = FloatPoint3D(x, y, z); | |
234 | |
235 if (m_position == position) | |
236 return; | |
237 | |
238 // This synchronizes with process(). | |
239 MutexLocker processLocker(m_processLock); | |
240 | |
241 m_position = position; | |
242 } | |
243 | |
244 void PannerNode::setOrientation(float x, float y, float z) | |
245 { | |
246 FloatPoint3D orientation = FloatPoint3D(x, y, z); | |
247 | |
248 if (m_orientation == orientation) | |
249 return; | |
250 | |
251 // This synchronizes with process(). | |
252 MutexLocker processLocker(m_processLock); | |
253 | |
254 m_orientation = orientation; | |
255 } | |
256 | |
257 void PannerNode::setVelocity(float x, float y, float z) | |
258 { | |
259 FloatPoint3D velocity = FloatPoint3D(x, y, z); | |
260 | |
261 if (m_velocity == velocity) | |
262 return; | |
263 | |
264 // This synchronizes with process(). | |
265 MutexLocker processLocker(m_processLock); | |
266 | |
267 m_velocity = velocity; | |
268 } | |
269 | |
270 String PannerNode::distanceModel() const | 222 String PannerNode::distanceModel() const |
271 { | 223 { |
272 switch (const_cast<PannerNode*>(this)->m_distanceEffect.model()) { | 224 switch (const_cast<PannerNode*>(this)->m_distanceEffect.model()) { |
273 case DistanceEffect::ModelLinear: | 225 case DistanceEffect::ModelLinear: |
274 return "linear"; | 226 return "linear"; |
275 case DistanceEffect::ModelInverse: | 227 case DistanceEffect::ModelInverse: |
276 return "inverse"; | 228 return "inverse"; |
277 case DistanceEffect::ModelExponential: | 229 case DistanceEffect::ModelExponential: |
278 return "exponential"; | 230 return "exponential"; |
279 default: | 231 default: |
(...skipping 25 matching lines...) Expand all Loading... | |
305 m_distanceModel = model; | 257 m_distanceModel = model; |
306 } | 258 } |
307 break; | 259 break; |
308 default: | 260 default: |
309 return false; | 261 return false; |
310 } | 262 } |
311 | 263 |
312 return true; | 264 return true; |
313 } | 265 } |
314 | 266 |
267 void PannerNode::setRefDistance(double distance) | |
268 { | |
269 if (refDistance() == distance) | |
270 return; | |
271 | |
272 // This synchronizes with process(). | |
273 MutexLocker processLocker(m_processLock); | |
274 m_distanceEffect.setRefDistance(distance); | |
275 updatePannerDirty(PannerNode::DistanceConeGainDirty); | |
276 } | |
277 | |
278 void PannerNode::setMaxDistance(double distance) | |
279 { | |
280 if (maxDistance() == distance) | |
281 return; | |
282 | |
283 // This synchronizes with process(). | |
284 MutexLocker processLocker(m_processLock); | |
285 m_distanceEffect.setMaxDistance(distance); | |
286 updatePannerDirty(PannerNode::DistanceConeGainDirty); | |
287 } | |
288 | |
289 void PannerNode::setRolloffFactor(double factor) | |
290 { | |
291 if (rolloffFactor() == factor) | |
292 return; | |
293 | |
294 // This synchronizes with process(). | |
295 MutexLocker processLocker(m_processLock); | |
296 m_distanceEffect.setRolloffFactor(factor); | |
297 updatePannerDirty(PannerNode::DistanceConeGainDirty); | |
298 } | |
299 | |
300 void PannerNode::setConeInnerAngle(double angle) | |
301 { | |
302 if (coneInnerAngle() == angle) | |
303 return; | |
304 | |
305 // This synchronizes with process(). | |
306 MutexLocker processLocker(m_processLock); | |
307 m_coneEffect.setInnerAngle(angle); | |
308 updatePannerDirty(PannerNode::DistanceConeGainDirty); | |
309 } | |
310 | |
311 void PannerNode::setConeOuterAngle(double angle) | |
312 { | |
313 if (coneOuterAngle() == angle) | |
314 return; | |
315 | |
316 // This synchronizes with process(). | |
317 MutexLocker processLocker(m_processLock); | |
318 m_coneEffect.setOuterAngle(angle); | |
319 updatePannerDirty(PannerNode::DistanceConeGainDirty); | |
320 } | |
321 | |
322 void PannerNode::setConeOuterGain(double angle) | |
323 { | |
324 if (coneOuterGain() == angle) | |
325 return; | |
326 | |
327 // This synchronizes with process(). | |
328 MutexLocker processLocker(m_processLock); | |
329 m_coneEffect.setOuterGain(angle); | |
330 updatePannerDirty(PannerNode::DistanceConeGainDirty); | |
331 } | |
332 | |
333 void PannerNode::setPosition(float x, float y, float z) | |
334 { | |
335 FloatPoint3D position = FloatPoint3D(x, y, z); | |
336 | |
337 if (m_position == position) | |
338 return; | |
339 | |
340 // This synchronizes with process(). | |
341 MutexLocker processLocker(m_processLock); | |
342 m_position = position; | |
343 updatePannerDirty(PannerNode::AzimuthElevationDirty | PannerNode::DistanceCo neGainDirty | PannerNode::DopplerRateDirty); | |
344 } | |
345 | |
346 void PannerNode::setOrientation(float x, float y, float z) | |
347 { | |
348 FloatPoint3D orientation = FloatPoint3D(x, y, z); | |
349 | |
350 if (m_orientation == orientation) | |
351 return; | |
352 | |
353 // This synchronizes with process(). | |
354 MutexLocker processLocker(m_processLock); | |
355 m_orientation = orientation; | |
356 updatePannerDirty(PannerNode::DistanceConeGainDirty); | |
357 } | |
358 | |
359 void PannerNode::setVelocity(float x, float y, float z) | |
360 { | |
361 FloatPoint3D velocity = FloatPoint3D(x, y, z); | |
362 | |
363 if (m_velocity == velocity) | |
364 return; | |
365 | |
366 // This synchronizes with process(). | |
367 MutexLocker processLocker(m_processLock); | |
368 m_velocity = velocity; | |
369 updatePannerDirty(PannerNode::DopplerRateDirty); | |
370 } | |
371 | |
315 void PannerNode::calculateAzimuthElevation(double* outAzimuth, double* outElevat ion) | 372 void PannerNode::calculateAzimuthElevation(double* outAzimuth, double* outElevat ion) |
316 { | 373 { |
317 double azimuth = 0.0; | 374 double azimuth = 0.0; |
318 | 375 |
319 // Calculate the source-listener vector | 376 // Calculate the source-listener vector |
320 FloatPoint3D listenerPosition = listener()->position(); | 377 FloatPoint3D listenerPosition = listener()->position(); |
321 FloatPoint3D sourceListener = m_position - listenerPosition; | 378 FloatPoint3D sourceListener = m_position - listenerPosition; |
322 | 379 |
323 if (sourceListener.isZero()) { | 380 if (sourceListener.isZero()) { |
324 // degenerate case if source and listener are at the same point | 381 // degenerate case if source and listener are at the same point |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
428 double distanceGain = m_distanceEffect.gain(listenerDistance); | 485 double distanceGain = m_distanceEffect.gain(listenerDistance); |
429 double coneGain = m_coneEffect.gain(m_position, m_orientation, listenerPosit ion); | 486 double coneGain = m_coneEffect.gain(m_position, m_orientation, listenerPosit ion); |
430 | 487 |
431 return float(distanceGain * coneGain); | 488 return float(distanceGain * coneGain); |
432 } | 489 } |
433 | 490 |
434 void PannerNode::azimuthElevation(double* outAzimuth, double* outElevation) | 491 void PannerNode::azimuthElevation(double* outAzimuth, double* outElevation) |
435 { | 492 { |
436 ASSERT(context()->isAudioThread()); | 493 ASSERT(context()->isAudioThread()); |
437 | 494 |
438 if (isAzimuthElevationDirty()) | 495 if (isAzimuthElevationDirty()) { |
439 calculateAzimuthElevation(&m_cachedAzimuth, &m_cachedElevation); | 496 calculateAzimuthElevation(&m_cachedAzimuth, &m_cachedElevation); |
497 m_isAzimuthElevationDirty = false; | |
498 } | |
440 | 499 |
441 *outAzimuth = m_cachedAzimuth; | 500 *outAzimuth = m_cachedAzimuth; |
442 *outElevation = m_cachedElevation; | 501 *outElevation = m_cachedElevation; |
443 } | 502 } |
444 | 503 |
445 double PannerNode::dopplerRate() | 504 double PannerNode::dopplerRate() |
446 { | 505 { |
447 ASSERT(context()->isAudioThread()); | 506 ASSERT(context()->isAudioThread()); |
448 | 507 |
449 if (isDopplerRateDirty()) | 508 if (isDopplerRateDirty()) { |
450 m_cachedDopplerRate = calculateDopplerRate(); | 509 m_cachedDopplerRate = calculateDopplerRate(); |
510 m_isDopplerRateDirty = false; | |
511 } | |
451 | 512 |
452 return m_cachedDopplerRate; | 513 return m_cachedDopplerRate; |
453 } | 514 } |
454 | 515 |
455 float PannerNode::distanceConeGain() | 516 float PannerNode::distanceConeGain() |
456 { | 517 { |
457 ASSERT(context()->isAudioThread()); | 518 ASSERT(context()->isAudioThread()); |
458 | 519 |
459 if (isDistanceConeGainDirty()) | 520 if (isDistanceConeGainDirty()) { |
460 m_cachedDistanceConeGain = calculateDistanceConeGain(); | 521 m_cachedDistanceConeGain = calculateDistanceConeGain(); |
522 m_isDistanceConeGainDirty = false; | |
523 } | |
461 | 524 |
462 return m_cachedDistanceConeGain; | 525 return m_cachedDistanceConeGain; |
463 } | 526 } |
464 | 527 |
465 bool PannerNode::isAzimuthElevationDirty() | 528 void PannerNode::updatePannerDirty(unsigned dirty) |
466 { | 529 { |
467 // Do a quick test and return if possible. | 530 if (dirty & PannerNode::AzimuthElevationDirty) |
468 if (m_cachedPosition != m_position) | 531 m_isAzimuthElevationDirty = true; |
469 return true; | |
470 | 532 |
471 if (m_cachedListener->position() != listener()->position() | 533 if (dirty & PannerNode::DistanceConeGainDirty) |
472 || m_cachedListener->orientation() != listener()->orientation() | 534 m_isDistanceConeGainDirty = true; |
473 || m_cachedListener->upVector() != listener()->upVector()) | |
474 return true; | |
475 | 535 |
476 return false; | 536 if (dirty & PannerNode::DopplerRateDirty) |
477 } | 537 m_isDopplerRateDirty = true; |
478 | |
479 bool PannerNode::isDistanceConeGainDirty() | |
480 { | |
481 // Do a quick test and return if possible. | |
482 if (m_cachedPosition != m_position || m_cachedOrientation != m_orientation) | |
483 return true; | |
484 | |
485 if (m_cachedListener->position() != listener()->position()) | |
486 return true; | |
487 | |
488 return false; | |
489 } | |
490 | |
491 bool PannerNode::isDopplerRateDirty() | |
492 { | |
493 // Do a quick test and return if possible. | |
494 if (m_cachedPosition != m_position || m_cachedVelocity != m_velocity) | |
495 return true; | |
496 | |
497 if (m_cachedListener->position() != listener()->position() | |
498 || m_cachedListener->velocity() != listener()->velocity() | |
499 || m_cachedListener->dopplerFactor() != listener()->dopplerFactor() | |
500 || m_cachedListener->speedOfSound() != listener()->speedOfSound()) | |
501 return true; | |
502 | |
503 return false; | |
504 } | 538 } |
505 | 539 |
506 void PannerNode::notifyAudioSourcesConnectedToNode(AudioNode* node, HashMap<Audi oNode*, bool>& visitedNodes) | 540 void PannerNode::notifyAudioSourcesConnectedToNode(AudioNode* node, HashMap<Audi oNode*, bool>& visitedNodes) |
507 { | 541 { |
508 ASSERT(node); | 542 ASSERT(node); |
509 if (!node) | 543 if (!node) |
510 return; | 544 return; |
511 | 545 |
512 // First check if this node is an AudioBufferSourceNode. If so, let it know about us so that doppler shift pitch can be taken into account. | 546 // First check if this node is an AudioBufferSourceNode. If so, let it know about us so that doppler shift pitch can be taken into account. |
513 if (node->nodeType() == NodeTypeAudioBufferSource) { | 547 if (node->nodeType() == NodeTypeAudioBufferSource) { |
(...skipping 14 matching lines...) Expand all Loading... | |
528 // mark it as visited and recurse through the node looking for s ources. | 562 // mark it as visited and recurse through the node looking for s ources. |
529 if (iterator == visitedNodes.end()) { | 563 if (iterator == visitedNodes.end()) { |
530 visitedNodes.set(connectedNode, true); | 564 visitedNodes.set(connectedNode, true); |
531 notifyAudioSourcesConnectedToNode(connectedNode, visitedNode s); // recurse | 565 notifyAudioSourcesConnectedToNode(connectedNode, visitedNode s); // recurse |
532 } | 566 } |
533 } | 567 } |
534 } | 568 } |
535 } | 569 } |
536 } | 570 } |
537 | 571 |
538 void PannerNode::updateCachedListener() | |
539 { | |
540 ASSERT(context()->isAudioThread()); | |
541 | |
542 m_cachedListener->setPosition(listener()->position()); | |
543 m_cachedListener->setOrientation(listener()->orientation()); | |
544 m_cachedListener->setUpVector(listener()->upVector()); | |
545 m_cachedListener->setVelocity(listener()->velocity()); | |
546 m_cachedListener->setDopplerFactor(listener()->dopplerFactor()); | |
547 m_cachedListener->setSpeedOfSound(listener()->speedOfSound()); | |
548 } | |
549 | |
550 void PannerNode::updateCachedSourceLocationInfo() | |
551 { | |
552 ASSERT(context()->isAudioThread()); | |
553 | |
554 m_cachedPosition = m_position; | |
555 m_cachedOrientation = m_orientation; | |
556 m_cachedVelocity = m_velocity; | |
557 } | |
558 | |
559 } // namespace WebCore | 572 } // namespace WebCore |
560 | 573 |
561 #endif // ENABLE(WEB_AUDIO) | 574 #endif // ENABLE(WEB_AUDIO) |
OLD | NEW |