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 "core/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 // renderingParamFanOutCount() is the number of AudioParams that we're connected to during rendering. 66 // Unlike paramFanOutCount() it will not change during the course of a render quantum. 67 unsigned renderingParamFanOutCount() const; 68 69 // Must be called with the context's graph lock. 70 void disconnectAll(); 71 72 void setNumberOfChannels(unsigned); 73 unsigned numberOfChannels() const { return m_numberOfChannels; } 74 bool isChannelCountKnown() const { return numberOfChannels() > 0; } 75 76 bool isConnected() { return fanOutCount() > 0 || paramFanOutCount() > 0; } 77 78 // Disable/Enable happens when there are still JavaScript references to a node, but it has otherwise "finished" its work. 79 // For example, when a note has finished playing. It is kept around, because it may be played again at a later time. 80 // They must be called with the context's graph lock. 81 void disable(); 82 void enable(); 83 84 // 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. 85 // It must be called with the context's graph lock. 86 void updateRenderingState(); 87 88 private: 89 AudioNode* m_node; 90 91 friend class AudioNodeInput; 92 friend class AudioParam; 93 94 // These are called from AudioNodeInput. 95 // They must be called with the context's graph lock. 96 void addInput(AudioNodeInput*); 97 void removeInput(AudioNodeInput*); 98 void addParam(AudioParam*); 99 void removeParam(AudioParam*); 100 101 // fanOutCount() is the number of AudioNodeInputs that we're connected to. 102 // This method should not be called in audio thread rendering code, instead renderingFanOutCount() should be used. 103 // It must be called with the context's graph lock. 104 unsigned fanOutCount(); 105 106 // Similar to fanOutCount(), paramFanOutCount() is the number of AudioParams that we're connected to. 107 // This method should not be called in audio thread rendering code, instead renderingParamFanOutCount() should be used. 108 // It must be called with the context's graph lock. 109 unsigned paramFanOutCount(); 110 111 // Must be called with the context's graph lock. 112 void disconnectAllInputs(); 113 void disconnectAllParams(); 114 115 // updateInternalBus() updates m_internalBus appropriately for the number of channels. 116 // It is called in the constructor or in the audio thread with the context's graph lock. 117 void updateInternalBus(); 118 119 // Announce to any nodes we're connected to that we changed our channel count for its input. 120 // It must be called in the audio thread with the context's graph lock. 121 void propagateChannelCount(); 122 123 // updateNumberOfChannels() is called in the audio thread at the start or end of the render quantum to pick up channel changes. 124 // It must be called with the context's graph lock. 125 void updateNumberOfChannels(); 126 127 // m_numberOfChannels will only be changed in the audio thread. 128 // The main thread sets m_desiredNumberOfChannels which will later get picked up in the audio thread in updateNumberOfChannels(). 129 unsigned m_numberOfChannels; 130 unsigned m_desiredNumberOfChannels; 131 132 // m_internalBus and m_inPlaceBus must only be changed in the audio thread with the context's graph lock (or constructor). 133 RefPtr<AudioBus> m_internalBus; 134 RefPtr<AudioBus> m_inPlaceBus; 135 // If m_isInPlace is true, use m_inPlaceBus as the valid AudioBus; If false, use the default m_internalBus. 136 bool m_isInPlace; 137 138 HashSet<AudioNodeInput*> m_inputs; 139 typedef HashSet<AudioNodeInput*>::iterator InputsIterator; 140 bool m_isEnabled; 141 142 // For the purposes of rendering, keeps track of the number of inputs and AudioParams we're connected to. 143 // These value should only be changed at the very start or end of the rendering quantum. 144 unsigned m_renderingFanOutCount; 145 unsigned m_renderingParamFanOutCount; 146 147 HashSet<RefPtr<AudioParam> > m_params; 148 typedef HashSet<RefPtr<AudioParam> >::iterator ParamsIterator; 149 }; 150 151 } // namespace WebCore 152 153 #endif // AudioNodeOutput_h 154