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 #include "wtf/Vector.h" 34 35 namespace WebCore { 36 37 class AudioContext; 38 class AudioNodeInput; 39 40 // AudioNodeOutput represents a single output for an AudioNode. 41 // It may be connected to one or more AudioNodeInputs. 42 43 class AudioNodeOutput { 44 public: 45 // It's OK to pass 0 for numberOfChannels in which case setNumberOfChannels() must be called later on. 46 AudioNodeOutput(AudioNode*, unsigned numberOfChannels); 47 48 // Can be called from any thread. 49 AudioNode* node() const { return m_node; } 50 AudioContext* context() { return m_node->context(); } 51 52 // Causes our AudioNode to process if it hasn't already for this render quantum. 53 // It returns the bus containing the processed audio for this output, returning inPlaceBus if in-place processing was possible. 54 // Called from context's audio thread. 55 AudioBus* pull(AudioBus* inPlaceBus, size_t framesToProcess); 56 57 // bus() will contain the rendered audio after pull() is called for each rendering time quantum. 58 // Called from context's audio thread. 59 AudioBus* bus() const; 60 61 // renderingFanOutCount() is the number of AudioNodeInputs that we're connected to during rendering. 62 // Unlike fanOutCount() it will not change during the course of a render quantum. 63 unsigned renderingFanOutCount() const; 64 65 // Must be called with the context's graph lock. 66 void disconnectAll(); 67 68 void setNumberOfChannels(unsigned); 69 unsigned numberOfChannels() const { return m_numberOfChannels; } 70 bool isChannelCountKnown() const { return numberOfChannels() > 0; } 71 72 bool isConnected() { return fanOutCount() > 0 || paramFanOutCount() > 0; } 73 74 // Disable/Enable happens when there are still JavaScript references to a node, but it has otherwise "finished" its work. 75 // For example, when a note has finished playing. It is kept around, because it may be played again at a later time. 76 // They must be called with the context's graph lock. 77 void disable(); 78 void enable(); 79 80 // 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. 81 // It must be called with the context's graph lock. 82 void updateRenderingState(); 83 84 private: 85 AudioNode* m_node; 86 87 friend class AudioNodeInput; 88 friend class AudioParam; 89 90 // These are called from AudioNodeInput. 91 // They must be called with the context's graph lock. 92 void addInput(AudioNodeInput*); 93 void removeInput(AudioNodeInput*); 94 void addParam(AudioParam*); 95 void removeParam(AudioParam*); 96 97 // fanOutCount() is the number of AudioNodeInputs that we're connected to. 98 // This method should not be called in audio thread rendering code, instead renderingFanOutCount() should be used. 99 // It must be called with the context's graph lock. 100 unsigned fanOutCount(); 101 102 // Similar to fanOutCount(), paramFanOutCount() is the number of AudioParams that we're connected to. 103 // This method should not be called in audio thread rendering code, instead renderingParamFanOutCount() should be used. 104 // It must be called with the context's graph lock. 105 unsigned paramFanOutCount(); 106 107 // Must be called with the context's graph lock. 108 void disconnectAllInputs(); 109 void disconnectAllParams(); 110 111 // updateInternalBus() updates m_internalBus appropriately for the number of channels. 112 // It is called in the constructor or in the audio thread with the context's graph lock. 113 void updateInternalBus(); 114 115 // Announce to any nodes we're connected to that we changed our channel count for its input. 116 // It must be called in the audio thread with the context's graph lock. 117 void propagateChannelCount(); 118 119 // updateNumberOfChannels() is called in the audio thread at the start or end of the render quantum to pick up channel changes. 120 // It must be called with the context's graph lock. 121 void updateNumberOfChannels(); 122 123 // m_numberOfChannels will only be changed in the audio thread. 124 // The main thread sets m_desiredNumberOfChannels which will later get picked up in the audio thread in updateNumberOfChannels(). 125 unsigned m_numberOfChannels; 126 unsigned m_desiredNumberOfChannels; 127 128 // m_internalBus and m_inPlaceBus must only be changed in the audio thread with the context's graph lock (or constructor). 129 RefPtr<AudioBus> m_internalBus; 130 RefPtr<AudioBus> m_inPlaceBus; 131 // If m_isInPlace is true, use m_inPlaceBus as the valid AudioBus; If false, use the default m_internalBus. 132 bool m_isInPlace; 133 134 HashSet<AudioNodeInput*> m_inputs; 135 typedef HashSet<AudioNodeInput*>::iterator InputsIterator; 136 bool m_isEnabled; 137 138 // For the purposes of rendering, keeps track of the number of inputs and AudioParams we're connected to. 139 // These value should only be changed at the very start or end of the rendering quantum. 140 unsigned m_renderingFanOutCount; 141 unsigned m_renderingParamFanOutCount; 142 143 WillBePersistentHeapHashSet<RefPtrWillBeMember<AudioParam> > m_params; 144 }; 145 146 } // namespace WebCore 147 148 #endif // AudioNodeOutput_h 149