Chromium Code Reviews| 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 |