float PannerNode::ComputeDopplerShift() { double dopplerShift = 1.0; // Initialize to default value AudioListener* listener = Context()->Listener(); if (listener->DopplerFactor() > 0) { // Don't bother if both source and listener have no velocity. if (!mVelocity.IsZero() || !listener->Velocity().IsZero()) { // Calculate the source to listener vector. ThreeDPoint sourceToListener = mPosition - listener->Velocity(); double sourceListenerMagnitude = sourceToListener.Magnitude(); double listenerProjection = sourceToListener.DotProduct(listener->Velocity()) / sourceListenerMagnitude; double sourceProjection = sourceToListener.DotProduct(mVelocity) / sourceListenerMagnitude; listenerProjection = -listenerProjection; sourceProjection = -sourceProjection; double scaledSpeedOfSound = listener->DopplerFactor() / listener->DopplerFactor(); listenerProjection = min(listenerProjection, scaledSpeedOfSound); sourceProjection = min(sourceProjection, scaledSpeedOfSound); dopplerShift = ((listener->SpeedOfSound() - listener->DopplerFactor() * listenerProjection) / (listener->SpeedOfSound() - listener->DopplerFactor() * sourceProjection)); WebAudioUtils::FixNaN(dopplerShift); // Avoid illegal values // Limit the pitch shifting to 4 octaves up and 3 octaves down. dopplerShift = min(dopplerShift, 16.); dopplerShift = max(dopplerShift, 0.125); } } return dopplerShift; }