1 /* 2 * Copyright (C) 2010, Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 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 ANY 17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 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 ON 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 22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25 #ifndef AudioNodeOutput_h 26 #define AudioNodeOutput_h 27 28 #include "platform/audio/AudioBus.h" 29 #include "modules/webaudio/AudioNode.h" 30 #include "modules/webaudio/AudioParam.h" 31 #include "wtf/HashSet.h" 32 #include "wtf/RefPtr.h" 33 34 namespace blink { 35 36 class AudioContext; 37 class AudioNodeInput; 38 39 // AudioNodeOutput represents a single output for an AudioNode. 40 // It may be connected to one or more AudioNodeInputs. 41 class AudioNodeOutput : public GarbageCollectedFinalized<AudioNodeOutput> { 42 public: 43 // It's OK to pass 0 for numberOfChannels in which case 44 // setNumberOfChannels() must be called later on. 45 static AudioNodeOutput* create(AudioNode*, unsigned numberOfChannels); 46 void trace(Visitor*); 47 void dispose(); 48 49 // Can be called from any thread. node()50 AudioNode* node() const { return m_node; } context()51 AudioContext* context() { return m_node->context(); } 52 53 // Causes our AudioNode to process if it hasn't already for this render quantum. 54 // It returns the bus containing the processed audio for this output, returning inPlaceBus if in-place processing was possible. 55 // Called from context's audio thread. 56 AudioBus* pull(AudioBus* inPlaceBus, size_t framesToProcess); 57 58 // bus() will contain the rendered audio after pull() is called for each rendering time quantum. 59 // Called from context's audio thread. 60 AudioBus* bus() const; 61 62 // renderingFanOutCount() is the number of AudioNodeInputs that we're connected to during rendering. 63 // Unlike fanOutCount() it will not change during the course of a render quantum. 64 unsigned renderingFanOutCount() const; 65 66 // Must be called with the context's graph lock. 67 void disconnectAll(); 68 69 void setNumberOfChannels(unsigned); numberOfChannels()70 unsigned numberOfChannels() const { return m_numberOfChannels; } isChannelCountKnown()71 bool isChannelCountKnown() const { return numberOfChannels() > 0; } 72 isConnected()73 bool isConnected() { return fanOutCount() > 0 || paramFanOutCount() > 0; } 74 75 // Disable/Enable happens when there are still JavaScript references to a node, but it has otherwise "finished" its work. 76 // For example, when a note has finished playing. It is kept around, because it may be played again at a later time. 77 // They must be called with the context's graph lock. 78 void disable(); 79 void enable(); 80 81 // updateRenderingState() is called in the audio thread at the start or end of the render quantum to handle any recent changes to the graph state. 82 // It must be called with the context's graph lock. 83 void updateRenderingState(); 84 85 private: 86 AudioNodeOutput(AudioNode*, unsigned numberOfChannels); 87 88 Member<AudioNode> m_node; 89 90 friend class AudioNodeInput; 91 friend class AudioParam; 92 93 // These are called from AudioNodeInput. 94 // They must be called with the context's graph lock. 95 void addInput(AudioNodeInput&); 96 void removeInput(AudioNodeInput&); 97 void addParam(AudioParam&); 98 void removeParam(AudioParam&); 99 100 // fanOutCount() is the number of AudioNodeInputs that we're connected to. 101 // This method should not be called in audio thread rendering code, instead renderingFanOutCount() should be used. 102 // It must be called with the context's graph lock. 103 unsigned fanOutCount(); 104 105 // Similar to fanOutCount(), paramFanOutCount() is the number of AudioParams that we're connected to. 106 // This method should not be called in audio thread rendering code, instead renderingParamFanOutCount() should be used. 107 // It must be called with the context's graph lock. 108 unsigned paramFanOutCount(); 109 110 // Must be called with the context's graph lock. 111 void disconnectAllInputs(); 112 void disconnectAllParams(); 113 114 // updateInternalBus() updates m_internalBus appropriately for the number of channels. 115 // It is called in the constructor or in the audio thread with the context's graph lock. 116 void updateInternalBus(); 117 118 // Announce to any nodes we're connected to that we changed our channel count for its input. 119 // It must be called in the audio thread with the context's graph lock. 120 void propagateChannelCount(); 121 122 // updateNumberOfChannels() is called in the audio thread at the start or end of the render quantum to pick up channel changes. 123 // It must be called with the context's graph lock. 124 void updateNumberOfChannels(); 125 126 // m_numberOfChannels will only be changed in the audio thread. 127 // The main thread sets m_desiredNumberOfChannels which will later get picked up in the audio thread in updateNumberOfChannels(). 128 unsigned m_numberOfChannels; 129 unsigned m_desiredNumberOfChannels; 130 131 // m_internalBus and m_inPlaceBus must only be changed in the audio thread with the context's graph lock (or constructor). 132 RefPtr<AudioBus> m_internalBus; 133 RefPtr<AudioBus> m_inPlaceBus; 134 // If m_isInPlace is true, use m_inPlaceBus as the valid AudioBus; If false, use the default m_internalBus. 135 bool m_isInPlace; 136 137 // Oilpan: This HashMap holds connection references. We must call 138 // AudioNode::makeConnection when we add an AudioNode to this, and must call 139 // AudioNode::breakConnection() when we remove an AudioNode from this. 140 HeapHashMap<Member<AudioNodeInput>, Member<AudioNode> > m_inputs; 141 typedef HeapHashMap<Member<AudioNodeInput>, Member<AudioNode> >::iterator InputsIterator; 142 bool m_isEnabled; 143 144 #if ENABLE_ASSERT 145 bool m_didCallDispose; 146 #endif 147 148 // For the purposes of rendering, keeps track of the number of inputs and AudioParams we're connected to. 149 // These value should only be changed at the very start or end of the rendering quantum. 150 unsigned m_renderingFanOutCount; 151 unsigned m_renderingParamFanOutCount; 152 153 HeapHashSet<Member<AudioParam> > m_params; 154 }; 155 156 } // namespace blink 157 158 #endif // AudioNodeOutput_h 159