| 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 |
| 11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
| 12 * | 12 * |
| 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND AN
Y | 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND AN
Y |
| 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 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 AN
Y | 16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR AN
Y |
| 17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 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 O
N | 19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND O
N |
| 20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 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 | 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. | 22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 23 */ | 23 */ |
| 24 | 24 |
| 25 #include "modules/webaudio/PannerNode.h" | 25 #include "modules/webaudio/PannerNode.h" |
| 26 #include "bindings/core/v8/ExceptionMessages.h" | 26 #include "bindings/core/v8/ExceptionMessages.h" |
| 27 #include "bindings/core/v8/ExceptionState.h" | 27 #include "bindings/core/v8/ExceptionState.h" |
| 28 #include "core/dom/ExceptionCode.h" | 28 #include "core/dom/ExceptionCode.h" |
| 29 #include "core/dom/ExecutionContext.h" | 29 #include "core/dom/ExecutionContext.h" |
| 30 #include "modules/webaudio/AbstractAudioContext.h" | |
| 31 #include "modules/webaudio/AudioBufferSourceNode.h" | 30 #include "modules/webaudio/AudioBufferSourceNode.h" |
| 32 #include "modules/webaudio/AudioNodeInput.h" | 31 #include "modules/webaudio/AudioNodeInput.h" |
| 33 #include "modules/webaudio/AudioNodeOutput.h" | 32 #include "modules/webaudio/AudioNodeOutput.h" |
| 33 #include "modules/webaudio/BaseAudioContext.h" |
| 34 #include "platform/Histogram.h" | 34 #include "platform/Histogram.h" |
| 35 #include "platform/audio/HRTFPanner.h" | 35 #include "platform/audio/HRTFPanner.h" |
| 36 #include "wtf/MathExtras.h" | 36 #include "wtf/MathExtras.h" |
| 37 | 37 |
| 38 namespace blink { | 38 namespace blink { |
| 39 | 39 |
| 40 static void fixNANs(double& x) | 40 static void fixNANs(double& x) |
| 41 { | 41 { |
| 42 if (std::isnan(x) || std::isinf(x)) | 42 if (std::isnan(x) || std::isinf(x)) |
| 43 x = 0.0; | 43 x = 0.0; |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 } | 127 } |
| 128 | 128 |
| 129 // The audio thread can't block on this lock, so we call tryLock() instead. | 129 // The audio thread can't block on this lock, so we call tryLock() instead. |
| 130 MutexTryLocker tryLocker(m_processLock); | 130 MutexTryLocker tryLocker(m_processLock); |
| 131 MutexTryLocker tryListenerLocker(listener()->listenerLock()); | 131 MutexTryLocker tryListenerLocker(listener()->listenerLock()); |
| 132 | 132 |
| 133 if (tryLocker.locked() && tryListenerLocker.locked()) { | 133 if (tryLocker.locked() && tryListenerLocker.locked()) { |
| 134 // HRTFDatabase should be loaded before proceeding when the panning mode
l is HRTF. | 134 // HRTFDatabase should be loaded before proceeding when the panning mode
l is HRTF. |
| 135 if (m_panningModel == Panner::PanningModelHRTF && !listener()->isHRTFDat
abaseLoaded()) { | 135 if (m_panningModel == Panner::PanningModelHRTF && !listener()->isHRTFDat
abaseLoaded()) { |
| 136 if (context()->hasRealtimeConstraint()) { | 136 if (context()->hasRealtimeConstraint()) { |
| 137 // Some AbstractAudioContexts cannot block on the HRTFDatabase l
oader. | 137 // Some BaseAudioContexts cannot block on the HRTFDatabase loade
r. |
| 138 destination->zero(); | 138 destination->zero(); |
| 139 return; | 139 return; |
| 140 } | 140 } |
| 141 | 141 |
| 142 listener()->waitForHRTFDatabaseLoaderThreadCompletion(); | 142 listener()->waitForHRTFDatabaseLoaderThreadCompletion(); |
| 143 } | 143 } |
| 144 | 144 |
| 145 if (hasSampleAccurateValues() || listener()->hasSampleAccurateValues())
{ | 145 if (hasSampleAccurateValues() || listener()->hasSampleAccurateValues())
{ |
| 146 // It's tempting to skip sample-accurate processing if isAzimuthElev
ationDirty() and | 146 // It's tempting to skip sample-accurate processing if isAzimuthElev
ationDirty() and |
| 147 // isDistanceConeGain() both return false. But in general we can't
because something | 147 // isDistanceConeGain() both return false. But in general we can't
because something |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 556 if (dirty & PannerHandler::AzimuthElevationDirty) | 556 if (dirty & PannerHandler::AzimuthElevationDirty) |
| 557 m_isAzimuthElevationDirty = true; | 557 m_isAzimuthElevationDirty = true; |
| 558 | 558 |
| 559 if (dirty & PannerHandler::DistanceConeGainDirty) | 559 if (dirty & PannerHandler::DistanceConeGainDirty) |
| 560 m_isDistanceConeGainDirty = true; | 560 m_isDistanceConeGainDirty = true; |
| 561 } | 561 } |
| 562 | 562 |
| 563 void PannerHandler::setChannelCount(unsigned long channelCount, ExceptionState&
exceptionState) | 563 void PannerHandler::setChannelCount(unsigned long channelCount, ExceptionState&
exceptionState) |
| 564 { | 564 { |
| 565 ASSERT(isMainThread()); | 565 ASSERT(isMainThread()); |
| 566 AbstractAudioContext::AutoLocker locker(context()); | 566 BaseAudioContext::AutoLocker locker(context()); |
| 567 | 567 |
| 568 // A PannerNode only supports 1 or 2 channels | 568 // A PannerNode only supports 1 or 2 channels |
| 569 if (channelCount > 0 && channelCount <= 2) { | 569 if (channelCount > 0 && channelCount <= 2) { |
| 570 if (m_channelCount != channelCount) { | 570 if (m_channelCount != channelCount) { |
| 571 m_channelCount = channelCount; | 571 m_channelCount = channelCount; |
| 572 if (m_channelCountMode != Max) | 572 if (m_channelCountMode != Max) |
| 573 updateChannelsForInputs(); | 573 updateChannelsForInputs(); |
| 574 } | 574 } |
| 575 } else { | 575 } else { |
| 576 exceptionState.throwDOMException( | 576 exceptionState.throwDOMException( |
| 577 NotSupportedError, | 577 NotSupportedError, |
| 578 ExceptionMessages::indexOutsideRange<unsigned long>( | 578 ExceptionMessages::indexOutsideRange<unsigned long>( |
| 579 "channelCount", | 579 "channelCount", |
| 580 channelCount, | 580 channelCount, |
| 581 1, | 581 1, |
| 582 ExceptionMessages::InclusiveBound, | 582 ExceptionMessages::InclusiveBound, |
| 583 2, | 583 2, |
| 584 ExceptionMessages::InclusiveBound)); | 584 ExceptionMessages::InclusiveBound)); |
| 585 } | 585 } |
| 586 } | 586 } |
| 587 | 587 |
| 588 void PannerHandler::setChannelCountMode(const String& mode, ExceptionState& exce
ptionState) | 588 void PannerHandler::setChannelCountMode(const String& mode, ExceptionState& exce
ptionState) |
| 589 { | 589 { |
| 590 ASSERT(isMainThread()); | 590 ASSERT(isMainThread()); |
| 591 AbstractAudioContext::AutoLocker locker(context()); | 591 BaseAudioContext::AutoLocker locker(context()); |
| 592 | 592 |
| 593 ChannelCountMode oldMode = m_channelCountMode; | 593 ChannelCountMode oldMode = m_channelCountMode; |
| 594 | 594 |
| 595 if (mode == "clamped-max") { | 595 if (mode == "clamped-max") { |
| 596 m_newChannelCountMode = ClampedMax; | 596 m_newChannelCountMode = ClampedMax; |
| 597 } else if (mode == "explicit") { | 597 } else if (mode == "explicit") { |
| 598 m_newChannelCountMode = Explicit; | 598 m_newChannelCountMode = Explicit; |
| 599 } else if (mode == "max") { | 599 } else if (mode == "max") { |
| 600 // This is not supported for a PannerNode, which can only handle 1 or 2
channels. | 600 // This is not supported for a PannerNode, which can only handle 1 or 2
channels. |
| 601 exceptionState.throwDOMException( | 601 exceptionState.throwDOMException( |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 633 | 633 |
| 634 if (hasMoved) { | 634 if (hasMoved) { |
| 635 m_lastPosition = currentPosition; | 635 m_lastPosition = currentPosition; |
| 636 m_lastOrientation = currentOrientation; | 636 m_lastOrientation = currentOrientation; |
| 637 | 637 |
| 638 markPannerAsDirty(PannerHandler::AzimuthElevationDirty | PannerHandler::
DistanceConeGainDirty); | 638 markPannerAsDirty(PannerHandler::AzimuthElevationDirty | PannerHandler::
DistanceConeGainDirty); |
| 639 } | 639 } |
| 640 } | 640 } |
| 641 // ---------------------------------------------------------------- | 641 // ---------------------------------------------------------------- |
| 642 | 642 |
| 643 PannerNode::PannerNode(AbstractAudioContext& context) | 643 PannerNode::PannerNode(BaseAudioContext& context) |
| 644 : AudioNode(context) | 644 : AudioNode(context) |
| 645 , m_positionX(AudioParam::create(context, ParamTypePannerPositionX, 0.0)) | 645 , m_positionX(AudioParam::create(context, ParamTypePannerPositionX, 0.0)) |
| 646 , m_positionY(AudioParam::create(context, ParamTypePannerPositionY, 0.0)) | 646 , m_positionY(AudioParam::create(context, ParamTypePannerPositionY, 0.0)) |
| 647 , m_positionZ(AudioParam::create(context, ParamTypePannerPositionZ, 0.0)) | 647 , m_positionZ(AudioParam::create(context, ParamTypePannerPositionZ, 0.0)) |
| 648 , m_orientationX(AudioParam::create(context, ParamTypePannerOrientationX, 1.
0)) | 648 , m_orientationX(AudioParam::create(context, ParamTypePannerOrientationX, 1.
0)) |
| 649 , m_orientationY(AudioParam::create(context, ParamTypePannerOrientationY, 0.
0)) | 649 , m_orientationY(AudioParam::create(context, ParamTypePannerOrientationY, 0.
0)) |
| 650 , m_orientationZ(AudioParam::create(context, ParamTypePannerOrientationZ, 0.
0)) | 650 , m_orientationZ(AudioParam::create(context, ParamTypePannerOrientationZ, 0.
0)) |
| 651 { | 651 { |
| 652 setHandler(PannerHandler::create( | 652 setHandler(PannerHandler::create( |
| 653 *this, | 653 *this, |
| 654 context.sampleRate(), | 654 context.sampleRate(), |
| 655 m_positionX->handler(), | 655 m_positionX->handler(), |
| 656 m_positionY->handler(), | 656 m_positionY->handler(), |
| 657 m_positionZ->handler(), | 657 m_positionZ->handler(), |
| 658 m_orientationX->handler(), | 658 m_orientationX->handler(), |
| 659 m_orientationY->handler(), | 659 m_orientationY->handler(), |
| 660 m_orientationZ->handler())); | 660 m_orientationZ->handler())); |
| 661 } | 661 } |
| 662 | 662 |
| 663 PannerNode* PannerNode::create(AbstractAudioContext& context, ExceptionState& ex
ceptionState) | 663 PannerNode* PannerNode::create(BaseAudioContext& context, ExceptionState& except
ionState) |
| 664 { | 664 { |
| 665 DCHECK(isMainThread()); | 665 DCHECK(isMainThread()); |
| 666 | 666 |
| 667 if (context.isContextClosed()) { | 667 if (context.isContextClosed()) { |
| 668 context.throwExceptionForClosedState(exceptionState); | 668 context.throwExceptionForClosedState(exceptionState); |
| 669 return nullptr; | 669 return nullptr; |
| 670 } | 670 } |
| 671 | 671 |
| 672 return new PannerNode(context); | 672 return new PannerNode(context); |
| 673 } | 673 } |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 780 visitor->trace(m_positionZ); | 780 visitor->trace(m_positionZ); |
| 781 | 781 |
| 782 visitor->trace(m_orientationX); | 782 visitor->trace(m_orientationX); |
| 783 visitor->trace(m_orientationY); | 783 visitor->trace(m_orientationY); |
| 784 visitor->trace(m_orientationZ); | 784 visitor->trace(m_orientationZ); |
| 785 | 785 |
| 786 AudioNode::trace(visitor); | 786 AudioNode::trace(visitor); |
| 787 } | 787 } |
| 788 | 788 |
| 789 } // namespace blink | 789 } // namespace blink |
| OLD | NEW |