OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "config.h" |
| 6 |
| 7 #if ENABLE(WEB_AUDIO) |
| 8 |
| 9 #include "modules/webaudio/StereoPannerNode.h" |
| 10 |
| 11 #include "bindings/core/v8/ExceptionMessages.h" |
| 12 #include "bindings/core/v8/ExceptionState.h" |
| 13 #include "core/dom/ExecutionContext.h" |
| 14 #include "modules/webaudio/AudioContext.h" |
| 15 #include "modules/webaudio/AudioNodeInput.h" |
| 16 #include "modules/webaudio/AudioNodeOutput.h" |
| 17 #include "platform/audio/StereoPanner.h" |
| 18 #include "wtf/MathExtras.h" |
| 19 |
| 20 namespace blink { |
| 21 |
| 22 StereoPannerNode::StereoPannerNode(AudioContext* context, float sampleRate) |
| 23 : AudioNode(context, sampleRate) |
| 24 , m_sampleAccuratePanValues(AudioNode::ProcessingSizeInFrames) |
| 25 { |
| 26 m_pan = AudioParam::create(context, 0); |
| 27 |
| 28 addInput(); |
| 29 addOutput(AudioNodeOutput::create(this, 2)); |
| 30 |
| 31 // The node-specific default mixing rules declare that StereoPannerNode |
| 32 // can handle mono to stereo and stereo to stereo conversion. |
| 33 m_channelCount = 2; |
| 34 m_channelCountMode = ClampedMax; |
| 35 m_channelInterpretation = AudioBus::Speakers; |
| 36 |
| 37 setNodeType(NodeTypeStereoPanner); |
| 38 |
| 39 initialize(); |
| 40 } |
| 41 |
| 42 StereoPannerNode::~StereoPannerNode() |
| 43 { |
| 44 ASSERT(!isInitialized()); |
| 45 } |
| 46 |
| 47 void StereoPannerNode::dispose() |
| 48 { |
| 49 uninitialize(); |
| 50 AudioNode::dispose(); |
| 51 } |
| 52 |
| 53 void StereoPannerNode::process(size_t framesToProcess) |
| 54 { |
| 55 AudioBus* outputBus = output(0)->bus(); |
| 56 |
| 57 if (!isInitialized() || !input(0)->isConnected() || !m_stereoPanner.get()) { |
| 58 outputBus->zero(); |
| 59 return; |
| 60 } |
| 61 |
| 62 AudioBus* inputBus = input(0)->bus(); |
| 63 if (!inputBus) { |
| 64 outputBus->zero(); |
| 65 return; |
| 66 } |
| 67 |
| 68 if (pan()->hasSampleAccurateValues()) { |
| 69 // Apply sample-accurate panning specified by AudioParam automation. |
| 70 ASSERT(framesToProcess <= m_sampleAccuratePanValues.size()); |
| 71 if (framesToProcess <= m_sampleAccuratePanValues.size()) { |
| 72 float* panValues = m_sampleAccuratePanValues.data(); |
| 73 pan()->calculateSampleAccurateValues(panValues, framesToProcess); |
| 74 m_stereoPanner->panWithSampleAccurateValues(inputBus, outputBus, pan
Values, framesToProcess); |
| 75 } |
| 76 } else { |
| 77 m_stereoPanner->panToTargetValue(inputBus, outputBus, pan()->value(), fr
amesToProcess); |
| 78 } |
| 79 } |
| 80 |
| 81 void StereoPannerNode::initialize() |
| 82 { |
| 83 if (isInitialized()) |
| 84 return; |
| 85 |
| 86 m_stereoPanner = Spatializer::create(Spatializer::PanningModelEqualPower, sa
mpleRate()); |
| 87 |
| 88 AudioNode::initialize(); |
| 89 } |
| 90 |
| 91 void StereoPannerNode::uninitialize() |
| 92 { |
| 93 if (!isInitialized()) |
| 94 return; |
| 95 |
| 96 m_stereoPanner.clear(); |
| 97 |
| 98 AudioNode::uninitialize(); |
| 99 } |
| 100 |
| 101 void StereoPannerNode::setChannelCount(unsigned long channelCount, ExceptionStat
e& exceptionState) |
| 102 { |
| 103 ASSERT(isMainThread()); |
| 104 AudioContext::AutoLocker locker(context()); |
| 105 |
| 106 // A PannerNode only supports 1 or 2 channels |
| 107 if (channelCount > 0 && channelCount <= 2) { |
| 108 if (m_channelCount != channelCount) { |
| 109 m_channelCount = channelCount; |
| 110 if (m_channelCountMode != Max) |
| 111 updateChannelsForInputs(); |
| 112 } |
| 113 } else { |
| 114 exceptionState.throwDOMException( |
| 115 NotSupportedError, |
| 116 ExceptionMessages::indexOutsideRange<unsigned long>( |
| 117 "channelCount", |
| 118 channelCount, |
| 119 1, |
| 120 ExceptionMessages::InclusiveBound, |
| 121 2, |
| 122 ExceptionMessages::InclusiveBound)); |
| 123 } |
| 124 } |
| 125 |
| 126 void StereoPannerNode::setChannelCountMode(const String& mode, ExceptionState& e
xceptionState) |
| 127 { |
| 128 ASSERT(isMainThread()); |
| 129 AudioContext::AutoLocker locker(context()); |
| 130 |
| 131 ChannelCountMode oldMode = m_channelCountMode; |
| 132 |
| 133 if (mode == "clamped-max") { |
| 134 m_newChannelCountMode = ClampedMax; |
| 135 } else if (mode == "explicit") { |
| 136 m_newChannelCountMode = Explicit; |
| 137 } else if (mode == "max") { |
| 138 // This is not supported for a StereoPannerNode, which can only handle |
| 139 // 1 or 2 channels. |
| 140 exceptionState.throwDOMException( |
| 141 NotSupportedError, |
| 142 ExceptionMessages::failedToSet( |
| 143 "channelCountMode", |
| 144 "StereoPannerNode", |
| 145 "'max' is not allowed")); |
| 146 m_newChannelCountMode = oldMode; |
| 147 } else { |
| 148 // Do nothing for other invalid values. |
| 149 m_newChannelCountMode = oldMode; |
| 150 } |
| 151 |
| 152 if (m_newChannelCountMode != oldMode) |
| 153 context()->addChangedChannelCountMode(this); |
| 154 } |
| 155 |
| 156 void StereoPannerNode::trace(Visitor* visitor) |
| 157 { |
| 158 visitor->trace(m_stereoPanner); |
| 159 visitor->trace(m_pan); |
| 160 AudioNode::trace(visitor); |
| 161 } |
| 162 |
| 163 } // namespace blink |
| 164 |
| 165 #endif // ENABLE(WEB_AUDIO) |
OLD | NEW |