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 AudioNode_h
26#define AudioNode_h
27
28#include <wtf/OwnPtr.h>
29#include <wtf/PassOwnPtr.h>
30#include <wtf/RefPtr.h>
31#include <wtf/Vector.h>
32
33#define DEBUG_AUDIONODE_REFERENCES 0
34
35namespace WebCore {
36
37class AudioContext;
38class AudioNodeInput;
39class AudioNodeOutput;
40
41// An AudioNode is the basic building block for handling audio within an AudioContext.
42// It may be an audio source, an intermediate processing module, or an audio destination.
43// Each AudioNode can have inputs and/or outputs. An AudioSourceNode has no inputs and a single output.
44// An AudioDestinationNode has one input and no outputs and represents the final destination to the audio hardware.
45// Most processing nodes such as filters will have one input and one output, although multiple inputs and outputs are possible.
46
47class AudioNode {
48public:
49    enum { ProcessingSizeInFrames = 128 };
50
51    AudioNode(AudioContext*, double sampleRate);
52    virtual ~AudioNode();
53
54    AudioContext* context() { return m_context.get(); }
55
56    enum NodeType {
57        NodeTypeUnknown,
58        NodeTypeDestination,
59        NodeTypeAudioBufferSource,
60        NodeTypeJavaScript,
61        NodeTypeLowPass2Filter,
62        NodeTypeHighPass2Filter,
63        NodeTypePanner,
64        NodeTypeConvolver,
65        NodeTypeDelay,
66        NodeTypeGain,
67        NodeTypeChannelSplitter,
68        NodeTypeChannelMerger,
69        NodeTypeAnalyser,
70        NodeTypeEnd
71    };
72
73    NodeType type() const { return m_type; }
74    void setType(NodeType);
75
76    // We handle our own ref-counting because of the threading issues and subtle nature of
77    // how AudioNodes can continue processing (playing one-shot sound) after there are no more
78    // JavaScript references to the object.
79    enum RefType { RefTypeNormal, RefTypeConnection, RefTypeDisabled };
80
81    // Can be called from main thread or context's audio thread.
82    void ref(RefType refType = RefTypeNormal);
83    void deref(RefType refType = RefTypeNormal);
84
85    // Can be called from main thread or context's audio thread.  It must be called while the context's graph lock is held.
86    void finishDeref(RefType refType);
87
88    // The AudioNodeInput(s) (if any) will already have their input data available when process() is called.
89    // Subclasses will take this input data and put the results in the AudioBus(s) of its AudioNodeOutput(s) (if any).
90    // Called from context's audio thread.
91    virtual void process(size_t framesToProcess) = 0;
92
93    // Resets DSP processing state (clears delay lines, filter memory, etc.)
94    // Called from context's audio thread.
95    virtual void reset() = 0;
96
97    // No significant resources should be allocated until initialize() is called.
98    // Processing may not occur until a node is initialized.
99    virtual void initialize();
100    virtual void uninitialize();
101
102    bool isInitialized() const { return m_isInitialized; }
103    void lazyInitialize();
104
105    unsigned numberOfInputs() const { return m_inputs.size(); }
106    unsigned numberOfOutputs() const { return m_outputs.size(); }
107
108    AudioNodeInput* input(unsigned);
109    AudioNodeOutput* output(unsigned);
110
111    // connect() / disconnect() return true on success.
112    // Called from main thread by corresponding JavaScript methods.
113    bool connect(AudioNode* destination, unsigned outputIndex = 0, unsigned inputIndex = 0);
114    bool disconnect(unsigned outputIndex = 0);
115
116    double sampleRate() const { return m_sampleRate; }
117
118    // processIfNecessary() is called by our output(s) when the rendering graph needs this AudioNode to process.
119    // This method ensures that the AudioNode will only process once per rendering time quantum even if it's called repeatedly.
120    // This handles the case of "fanout" where an output is connected to multiple AudioNode inputs.
121    // Called from context's audio thread.
122    void processIfNecessary(size_t framesToProcess);
123
124    // Called when a new connection has been made to one of our inputs or the connection number of channels has changed.
125    // This potentially gives us enough information to perform a lazy initialization or, if necessary, a re-initialization.
126    // Called from main thread.
127    virtual void checkNumberOfChannelsForInput(AudioNodeInput*) { }
128
129#if DEBUG_AUDIONODE_REFERENCES
130    static void printNodeCounts();
131#endif
132
133    bool isMarkedForDeletion() const { return m_isMarkedForDeletion; }
134
135protected:
136    // Inputs and outputs must be created before the AudioNode is initialized.
137    void addInput(PassOwnPtr<AudioNodeInput>);
138    void addOutput(PassOwnPtr<AudioNodeOutput>);
139
140    // Called by processIfNecessary() to cause all parts of the rendering graph connected to us to process.
141    // Each rendering quantum, the audio data for each of the AudioNode's inputs will be available after this method is called.
142    // Called from context's audio thread.
143    virtual void pullInputs(size_t framesToProcess);
144
145private:
146    volatile bool m_isInitialized;
147    NodeType m_type;
148    RefPtr<AudioContext> m_context;
149    double m_sampleRate;
150    Vector<OwnPtr<AudioNodeInput> > m_inputs;
151    Vector<OwnPtr<AudioNodeOutput> > m_outputs;
152
153    double m_lastProcessingTime;
154
155    // Ref-counting
156    volatile int m_normalRefCount;
157    volatile int m_connectionRefCount;
158    volatile int m_disabledRefCount;
159
160    bool m_isMarkedForDeletion;
161    bool m_isDisabled;
162
163#if DEBUG_AUDIONODE_REFERENCES
164    static bool s_isNodeCountInitialized;
165    static int s_nodeCount[NodeTypeEnd];
166#endif
167};
168
169} // namespace WebCore
170
171#endif // AudioNode_h
172