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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
46 x = 0.0; | 46 x = 0.0; |
47 } | 47 } |
48 | 48 |
49 PannerNode::PannerNode(AudioContext* context, float sampleRate) | 49 PannerNode::PannerNode(AudioContext* context, float sampleRate) |
50 : AudioNode(context, sampleRate) | 50 : AudioNode(context, sampleRate) |
51 , m_panningModel(Panner::PanningModelHRTF) | 51 , m_panningModel(Panner::PanningModelHRTF) |
52 , m_distanceModel(DistanceEffect::ModelInverse) | 52 , m_distanceModel(DistanceEffect::ModelInverse) |
53 , m_position(0, 0, 0) | 53 , m_position(0, 0, 0) |
54 , m_orientation(1, 0, 0) | 54 , m_orientation(1, 0, 0) |
55 , m_velocity(0, 0, 0) | 55 , m_velocity(0, 0, 0) |
56 , m_cachedPosition(0, 0, 0) | 56 , m_isAzimuthElevationDirty(true) |
57 , m_cachedOrientation(1, 0, 0) | 57 , m_isDistanceConeGainDirty(true) |
58 , m_cachedVelocity(0, 0, 0) | 58 , m_isDopplerRateDirty(true) |
59 , m_lastGain(-1.0) | 59 , m_lastGain(-1.0) |
60 , m_cachedAzimuth(0) | 60 , m_cachedAzimuth(0) |
61 , m_cachedElevation(0) | 61 , m_cachedElevation(0) |
62 , m_cachedDistanceConeGain(1.0f) | 62 , m_cachedDistanceConeGain(1.0f) |
63 , m_cachedDopplerRate(1) | 63 , m_cachedDopplerRate(1) |
64 , m_connectionCount(0) | 64 , m_connectionCount(0) |
65 { | 65 { |
66 // Load the HRTF database asynchronously so we don't block the Javascript th read while creating the HRTF database. | 66 // 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. | 67 // The HRTF panner will return zeroes until the database is loaded. |
68 m_hrtfDatabaseLoader = HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNece ssary(context->sampleRate()); | 68 m_hrtfDatabaseLoader = HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNece ssary(context->sampleRate()); |
69 | 69 |
70 ScriptWrappable::init(this); | 70 ScriptWrappable::init(this); |
71 addInput(adoptPtr(new AudioNodeInput(this))); | 71 addInput(adoptPtr(new AudioNodeInput(this))); |
72 addOutput(adoptPtr(new AudioNodeOutput(this, 2))); | 72 addOutput(adoptPtr(new AudioNodeOutput(this, 2))); |
73 | 73 |
74 // Node-specific default mixing rules. | 74 // Node-specific default mixing rules. |
75 m_channelCount = 2; | 75 m_channelCount = 2; |
76 m_channelCountMode = ClampedMax; | 76 m_channelCountMode = ClampedMax; |
77 m_channelInterpretation = AudioBus::Speakers; | 77 m_channelInterpretation = AudioBus::Speakers; |
78 | 78 |
79 m_cachedListener = AudioListener::create(); | |
80 | |
81 setNodeType(NodeTypePanner); | 79 setNodeType(NodeTypePanner); |
82 | 80 |
83 initialize(); | 81 initialize(); |
84 } | 82 } |
85 | 83 |
86 PannerNode::~PannerNode() | 84 PannerNode::~PannerNode() |
87 { | 85 { |
88 uninitialize(); | 86 uninitialize(); |
89 } | 87 } |
90 | 88 |
(...skipping 25 matching lines...) Expand all Loading... | |
116 } | 114 } |
117 | 115 |
118 AudioBus* source = input(0)->bus(); | 116 AudioBus* source = input(0)->bus(); |
119 if (!source) { | 117 if (!source) { |
120 destination->zero(); | 118 destination->zero(); |
121 return; | 119 return; |
122 } | 120 } |
123 | 121 |
124 // The audio thread can't block on this lock, so we call tryLock() instead. | 122 // The audio thread can't block on this lock, so we call tryLock() instead. |
125 MutexTryLocker tryLocker(m_processLock); | 123 MutexTryLocker tryLocker(m_processLock); |
126 if (tryLocker.locked()) { | 124 MutexTryLocker tryListenerLocker(listener()->listenerLock()); |
125 | |
126 if (tryLocker.locked() && tryListenerLocker.locked()) { | |
127 // HRTFDatabase should be loaded before proceeding for offline audio con text when the panning model is HRTF. | 127 // 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()) { | 128 if (m_panningModel == HRTF && !m_hrtfDatabaseLoader->isLoaded()) { |
129 if (context()->isOfflineContext()) { | 129 if (context()->isOfflineContext()) { |
130 m_hrtfDatabaseLoader->waitForLoaderThreadCompletion(); | 130 m_hrtfDatabaseLoader->waitForLoaderThreadCompletion(); |
131 } else { | 131 } else { |
132 destination->zero(); | 132 destination->zero(); |
133 return; | 133 return; |
134 } | 134 } |
135 } | 135 } |
136 | 136 |
137 // Apply the panning effect. | 137 // Apply the panning effect. |
138 double azimuth; | 138 double azimuth; |
139 double elevation; | 139 double elevation; |
140 azimuthElevation(&azimuth, &elevation); | 140 azimuthElevation(&azimuth, &elevation); |
141 | 141 |
142 m_panner->pan(azimuth, elevation, source, destination, framesToProcess); | 142 m_panner->pan(azimuth, elevation, source, destination, framesToProcess); |
143 | 143 |
144 // Get the distance and cone gain. | 144 // Get the distance and cone gain. |
145 float totalGain = distanceConeGain(); | 145 float totalGain = distanceConeGain(); |
146 | 146 |
147 // Snap to desired gain at the beginning. | 147 // Snap to desired gain at the beginning. |
148 if (m_lastGain == -1.0) | 148 if (m_lastGain == -1.0) |
149 m_lastGain = totalGain; | 149 m_lastGain = totalGain; |
150 | 150 |
151 // Apply gain in-place with de-zippering. | 151 // Apply gain in-place with de-zippering. |
152 destination->copyWithGainFrom(*destination, &m_lastGain, totalGain); | 152 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 { | 153 } else { |
159 // Too bad - The tryLock() failed. | 154 // 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. | 155 // We must be in the middle of changing the panning model, source's loca tion information, listener, distance parameters and sound cones. |
Raymond Toy
2014/04/16 17:36:15
Maybe simplify comment to just:
// We must be in
KhNo
2014/04/17 13:41:03
Done.
| |
161 destination->zero(); | 156 destination->zero(); |
162 } | 157 } |
163 } | 158 } |
164 | 159 |
165 void PannerNode::initialize() | 160 void PannerNode::initialize() |
166 { | 161 { |
167 if (isInitialized()) | 162 if (isInitialized()) |
168 return; | 163 return; |
169 | 164 |
170 m_panner = Panner::create(m_panningModel, sampleRate(), m_hrtfDatabaseLoader .get()); | 165 m_panner = Panner::create(m_panningModel, sampleRate(), m_hrtfDatabaseLoader .get()); |
166 listener()->addPanner(this); | |
Raymond Toy
2014/04/16 17:36:15
This happens in the main thread, but the processin
KhNo
2014/04/17 13:41:03
No, It doesn't happen. panners list in AudioListen
| |
171 | 167 |
172 AudioNode::initialize(); | 168 AudioNode::initialize(); |
173 } | 169 } |
174 | 170 |
175 void PannerNode::uninitialize() | 171 void PannerNode::uninitialize() |
176 { | 172 { |
177 if (!isInitialized()) | 173 if (!isInitialized()) |
178 return; | 174 return; |
179 | 175 |
180 m_panner.clear(); | 176 m_panner.clear(); |
177 listener()->removePanner(this); | |
Raymond Toy
2014/04/16 17:36:15
Is there a race condition here? You've cleared the
KhNo
2014/04/17 13:41:03
No, It doesn't happen. panners list in AudioListen
| |
178 | |
181 AudioNode::uninitialize(); | 179 AudioNode::uninitialize(); |
182 } | 180 } |
183 | 181 |
184 AudioListener* PannerNode::listener() | 182 AudioListener* PannerNode::listener() |
185 { | 183 { |
186 return context()->listener(); | 184 return context()->listener(); |
187 } | 185 } |
188 | 186 |
189 String PannerNode::panningModel() const | 187 String PannerNode::panningModel() const |
190 { | 188 { |
191 switch (m_panningModel) { | 189 switch (m_panningModel) { |
192 case EQUALPOWER: | 190 case EqualPower: |
193 return "equalpower"; | 191 return "equalpower"; |
194 case HRTF: | 192 case HRTF: |
195 return "HRTF"; | 193 return "HRTF"; |
196 default: | 194 default: |
197 ASSERT_NOT_REACHED(); | 195 ASSERT_NOT_REACHED(); |
198 return "HRTF"; | 196 return "HRTF"; |
199 } | 197 } |
200 } | 198 } |
201 | 199 |
202 void PannerNode::setPanningModel(const String& model) | 200 void PannerNode::setPanningModel(const String& model) |
203 { | 201 { |
204 if (model == "equalpower") | 202 if (model == "equalpower") |
205 setPanningModel(EQUALPOWER); | 203 setPanningModel(EqualPower); |
206 else if (model == "HRTF") | 204 else if (model == "HRTF") |
207 setPanningModel(HRTF); | 205 setPanningModel(HRTF); |
208 } | 206 } |
209 | 207 |
210 bool PannerNode::setPanningModel(unsigned model) | 208 bool PannerNode::setPanningModel(unsigned model) |
211 { | 209 { |
212 switch (model) { | 210 switch (model) { |
213 case EQUALPOWER: | 211 case EqualPower: |
214 case HRTF: | 212 case HRTF: |
215 if (!m_panner.get() || model != m_panningModel) { | 213 if (!m_panner.get() || model != m_panningModel) { |
216 // This synchronizes with process(). | 214 // This synchronizes with process(). |
217 MutexLocker processLocker(m_processLock); | 215 MutexLocker processLocker(m_processLock); |
218 | |
219 OwnPtr<Panner> newPanner = Panner::create(model, sampleRate(), m_hrt fDatabaseLoader.get()); | 216 OwnPtr<Panner> newPanner = Panner::create(model, sampleRate(), m_hrt fDatabaseLoader.get()); |
220 m_panner = newPanner.release(); | 217 m_panner = newPanner.release(); |
221 m_panningModel = model; | 218 m_panningModel = model; |
222 } | 219 } |
223 break; | 220 break; |
224 default: | 221 default: |
225 return false; | 222 return false; |
226 } | 223 } |
227 | 224 |
228 return true; | 225 return true; |
229 } | 226 } |
230 | 227 |
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 | 228 String PannerNode::distanceModel() const |
271 { | 229 { |
272 switch (const_cast<PannerNode*>(this)->m_distanceEffect.model()) { | 230 switch (const_cast<PannerNode*>(this)->m_distanceEffect.model()) { |
273 case DistanceEffect::ModelLinear: | 231 case DistanceEffect::ModelLinear: |
274 return "linear"; | 232 return "linear"; |
275 case DistanceEffect::ModelInverse: | 233 case DistanceEffect::ModelInverse: |
276 return "inverse"; | 234 return "inverse"; |
277 case DistanceEffect::ModelExponential: | 235 case DistanceEffect::ModelExponential: |
278 return "exponential"; | 236 return "exponential"; |
279 default: | 237 default: |
(...skipping 25 matching lines...) Expand all Loading... | |
305 m_distanceModel = model; | 263 m_distanceModel = model; |
306 } | 264 } |
307 break; | 265 break; |
308 default: | 266 default: |
309 return false; | 267 return false; |
310 } | 268 } |
311 | 269 |
312 return true; | 270 return true; |
313 } | 271 } |
314 | 272 |
273 void PannerNode::setRefDistance(double distance) | |
274 { | |
275 if (refDistance() == distance) | |
276 return; | |
277 | |
278 // This synchronizes with process(). | |
279 MutexLocker processLocker(m_processLock); | |
280 m_distanceEffect.setRefDistance(distance); | |
281 updatePannerDirty(PannerNode::DistanceConeGainDirty); | |
282 } | |
283 | |
284 void PannerNode::setMaxDistance(double distance) | |
285 { | |
286 if (maxDistance() == distance) | |
287 return; | |
288 | |
289 // This synchronizes with process(). | |
290 MutexLocker processLocker(m_processLock); | |
291 m_distanceEffect.setMaxDistance(distance); | |
292 updatePannerDirty(PannerNode::DistanceConeGainDirty); | |
293 } | |
294 | |
295 void PannerNode::setRolloffFactor(double factor) | |
296 { | |
297 if (rolloffFactor() == factor) | |
298 return; | |
299 | |
300 // This synchronizes with process(). | |
301 MutexLocker processLocker(m_processLock); | |
302 m_distanceEffect.setRolloffFactor(factor); | |
303 updatePannerDirty(PannerNode::DistanceConeGainDirty); | |
304 } | |
305 | |
306 void PannerNode::setConeInnerAngle(double angle) | |
307 { | |
308 if (coneInnerAngle() == angle) | |
309 return; | |
310 | |
311 // This synchronizes with process(). | |
312 MutexLocker processLocker(m_processLock); | |
313 m_coneEffect.setInnerAngle(angle); | |
314 updatePannerDirty(PannerNode::DistanceConeGainDirty); | |
315 } | |
316 | |
317 void PannerNode::setConeOuterAngle(double angle) | |
318 { | |
319 if (coneOuterAngle() == angle) | |
320 return; | |
321 | |
322 // This synchronizes with process(). | |
323 MutexLocker processLocker(m_processLock); | |
324 m_coneEffect.setOuterAngle(angle); | |
325 updatePannerDirty(PannerNode::DistanceConeGainDirty); | |
326 } | |
327 | |
328 void PannerNode::setConeOuterGain(double angle) | |
329 { | |
330 if (coneOuterGain() == angle) | |
331 return; | |
332 | |
333 // This synchronizes with process(). | |
334 MutexLocker processLocker(m_processLock); | |
335 m_coneEffect.setOuterGain(angle); | |
336 updatePannerDirty(PannerNode::DistanceConeGainDirty); | |
337 } | |
338 | |
339 void PannerNode::setPosition(float x, float y, float z) | |
340 { | |
341 FloatPoint3D position = FloatPoint3D(x, y, z); | |
342 | |
343 if (m_position == position) | |
344 return; | |
345 | |
346 // This synchronizes with process(). | |
347 MutexLocker processLocker(m_processLock); | |
348 m_position = position; | |
349 updatePannerDirty(PannerNode::AzimuthElevationDirty | PannerNode::DistanceCo neGainDirty | PannerNode::DopplerRateDirty); | |
350 } | |
351 | |
352 void PannerNode::setOrientation(float x, float y, float z) | |
353 { | |
354 FloatPoint3D orientation = FloatPoint3D(x, y, z); | |
355 | |
356 if (m_orientation == orientation) | |
357 return; | |
358 | |
359 // This synchronizes with process(). | |
360 MutexLocker processLocker(m_processLock); | |
361 m_orientation = orientation; | |
362 updatePannerDirty(PannerNode::DistanceConeGainDirty); | |
363 } | |
364 | |
365 void PannerNode::setVelocity(float x, float y, float z) | |
366 { | |
367 FloatPoint3D velocity = FloatPoint3D(x, y, z); | |
368 | |
369 if (m_velocity == velocity) | |
370 return; | |
371 | |
372 // This synchronizes with process(). | |
373 MutexLocker processLocker(m_processLock); | |
374 m_velocity = velocity; | |
375 updatePannerDirty(PannerNode::DopplerRateDirty); | |
376 } | |
377 | |
315 void PannerNode::calculateAzimuthElevation(double* outAzimuth, double* outElevat ion) | 378 void PannerNode::calculateAzimuthElevation(double* outAzimuth, double* outElevat ion) |
316 { | 379 { |
317 double azimuth = 0.0; | 380 double azimuth = 0.0; |
318 | 381 |
319 // Calculate the source-listener vector | 382 // Calculate the source-listener vector |
320 FloatPoint3D listenerPosition = listener()->position(); | 383 FloatPoint3D listenerPosition = listener()->position(); |
321 FloatPoint3D sourceListener = m_position - listenerPosition; | 384 FloatPoint3D sourceListener = m_position - listenerPosition; |
322 | 385 |
323 if (sourceListener.isZero()) { | 386 if (sourceListener.isZero()) { |
324 // degenerate case if source and listener are at the same point | 387 // 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); | 491 double distanceGain = m_distanceEffect.gain(listenerDistance); |
429 double coneGain = m_coneEffect.gain(m_position, m_orientation, listenerPosit ion); | 492 double coneGain = m_coneEffect.gain(m_position, m_orientation, listenerPosit ion); |
430 | 493 |
431 return float(distanceGain * coneGain); | 494 return float(distanceGain * coneGain); |
432 } | 495 } |
433 | 496 |
434 void PannerNode::azimuthElevation(double* outAzimuth, double* outElevation) | 497 void PannerNode::azimuthElevation(double* outAzimuth, double* outElevation) |
435 { | 498 { |
436 ASSERT(context()->isAudioThread()); | 499 ASSERT(context()->isAudioThread()); |
437 | 500 |
438 if (isAzimuthElevationDirty()) | 501 if (isAzimuthElevationDirty()) { |
439 calculateAzimuthElevation(&m_cachedAzimuth, &m_cachedElevation); | 502 calculateAzimuthElevation(&m_cachedAzimuth, &m_cachedElevation); |
503 m_isAzimuthElevationDirty = false; | |
504 } | |
440 | 505 |
441 *outAzimuth = m_cachedAzimuth; | 506 *outAzimuth = m_cachedAzimuth; |
442 *outElevation = m_cachedElevation; | 507 *outElevation = m_cachedElevation; |
443 } | 508 } |
444 | 509 |
445 double PannerNode::dopplerRate() | 510 double PannerNode::dopplerRate() |
446 { | 511 { |
447 ASSERT(context()->isAudioThread()); | 512 ASSERT(context()->isAudioThread()); |
448 | 513 |
449 if (isDopplerRateDirty()) | 514 if (isDopplerRateDirty()) { |
450 m_cachedDopplerRate = calculateDopplerRate(); | 515 m_cachedDopplerRate = calculateDopplerRate(); |
516 m_isDopplerRateDirty = false; | |
517 } | |
451 | 518 |
452 return m_cachedDopplerRate; | 519 return m_cachedDopplerRate; |
453 } | 520 } |
454 | 521 |
455 float PannerNode::distanceConeGain() | 522 float PannerNode::distanceConeGain() |
456 { | 523 { |
457 ASSERT(context()->isAudioThread()); | 524 ASSERT(context()->isAudioThread()); |
458 | 525 |
459 if (isDistanceConeGainDirty()) | 526 if (isDistanceConeGainDirty()) { |
460 m_cachedDistanceConeGain = calculateDistanceConeGain(); | 527 m_cachedDistanceConeGain = calculateDistanceConeGain(); |
528 m_isDistanceConeGainDirty = false; | |
529 } | |
461 | 530 |
462 return m_cachedDistanceConeGain; | 531 return m_cachedDistanceConeGain; |
463 } | 532 } |
464 | 533 |
465 bool PannerNode::isAzimuthElevationDirty() | 534 void PannerNode::updatePannerDirty(unsigned dirty) |
Raymond Toy
2014/04/16 17:36:15
I think the name markPannerAsDirty is more explici
KhNo
2014/04/17 13:41:03
Done.
| |
466 { | 535 { |
467 // Do a quick test and return if possible. | 536 if (dirty & PannerNode::AzimuthElevationDirty) |
468 if (m_cachedPosition != m_position) | 537 m_isAzimuthElevationDirty = true; |
469 return true; | |
470 | 538 |
471 if (m_cachedListener->position() != listener()->position() | 539 if (dirty & PannerNode::DistanceConeGainDirty) |
472 || m_cachedListener->orientation() != listener()->orientation() | 540 m_isDistanceConeGainDirty = true; |
473 || m_cachedListener->upVector() != listener()->upVector()) | |
474 return true; | |
475 | 541 |
476 return false; | 542 if (dirty & PannerNode::DopplerRateDirty) |
477 } | 543 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 } | 544 } |
505 | 545 |
506 void PannerNode::notifyAudioSourcesConnectedToNode(AudioNode* node, HashMap<Audi oNode*, bool>& visitedNodes) | 546 void PannerNode::notifyAudioSourcesConnectedToNode(AudioNode* node, HashMap<Audi oNode*, bool>& visitedNodes) |
507 { | 547 { |
508 ASSERT(node); | 548 ASSERT(node); |
509 if (!node) | 549 if (!node) |
510 return; | 550 return; |
511 | 551 |
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. | 552 // 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) { | 553 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. | 568 // mark it as visited and recurse through the node looking for s ources. |
529 if (iterator == visitedNodes.end()) { | 569 if (iterator == visitedNodes.end()) { |
530 visitedNodes.set(connectedNode, true); | 570 visitedNodes.set(connectedNode, true); |
531 notifyAudioSourcesConnectedToNode(connectedNode, visitedNode s); // recurse | 571 notifyAudioSourcesConnectedToNode(connectedNode, visitedNode s); // recurse |
532 } | 572 } |
533 } | 573 } |
534 } | 574 } |
535 } | 575 } |
536 } | 576 } |
537 | 577 |
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 | 578 } // namespace WebCore |
560 | 579 |
561 #endif // ENABLE(WEB_AUDIO) | 580 #endif // ENABLE(WEB_AUDIO) |
OLD | NEW |