1bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen/*
2e14391e94c850b8bd03680c23b38978db68687a8John Reck * Copyright (C) 2010, Google Inc. All rights reserved.
3bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen *
4bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * Redistribution and use in source and binary forms, with or without
5bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * modification, are permitted provided that the following conditions
6bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * are met:
7bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * 1.  Redistributions of source code must retain the above copyright
8e14391e94c850b8bd03680c23b38978db68687a8John Reck *    notice, this list of conditions and the following disclaimer.
9bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * 2.  Redistributions in binary form must reproduce the above copyright
10e14391e94c850b8bd03680c23b38978db68687a8John Reck *    notice, this list of conditions and the following disclaimer in the
11e14391e94c850b8bd03680c23b38978db68687a8John Reck *    documentation and/or other materials provided with the distribution.
12bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen *
13e14391e94c850b8bd03680c23b38978db68687a8John Reck * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16e14391e94c850b8bd03680c23b38978db68687a8John Reck * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19e14391e94c850b8bd03680c23b38978db68687a8John Reck * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20e14391e94c850b8bd03680c23b38978db68687a8John Reck * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21e14391e94c850b8bd03680c23b38978db68687a8John Reck * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22e14391e94c850b8bd03680c23b38978db68687a8John Reck * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen */
24bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
25bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#ifndef AudioNode_h
26bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#define AudioNode_h
27bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
28bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include <wtf/OwnPtr.h>
29bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include <wtf/PassOwnPtr.h>
30bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include <wtf/RefPtr.h>
31bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include <wtf/Vector.h>
32bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
33bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#define DEBUG_AUDIONODE_REFERENCES 0
34bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
35bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsennamespace WebCore {
36bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
37bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenclass AudioContext;
38bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenclass AudioNodeInput;
39bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenclass AudioNodeOutput;
40bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
41bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen// An AudioNode is the basic building block for handling audio within an AudioContext.
42bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen// It may be an audio source, an intermediate processing module, or an audio destination.
43bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen// Each AudioNode can have inputs and/or outputs. An AudioSourceNode has no inputs and a single output.
44bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen// An AudioDestinationNode has one input and no outputs and represents the final destination to the audio hardware.
45bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen// Most processing nodes such as filters will have one input and one output, although multiple inputs and outputs are possible.
46bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
47bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenclass AudioNode {
48bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenpublic:
49bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    enum { ProcessingSizeInFrames = 128 };
50bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
51bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    AudioNode(AudioContext*, double sampleRate);
52bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    virtual ~AudioNode();
53bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
54bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    AudioContext* context() { return m_context.get(); }
55bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
56bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    enum NodeType {
57bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        NodeTypeUnknown,
58bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        NodeTypeDestination,
59bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        NodeTypeAudioBufferSource,
60bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        NodeTypeJavaScript,
61bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        NodeTypeLowPass2Filter,
62bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        NodeTypeHighPass2Filter,
63bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        NodeTypePanner,
64bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        NodeTypeConvolver,
65bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        NodeTypeDelay,
66bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        NodeTypeGain,
67bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        NodeTypeChannelSplitter,
68bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        NodeTypeChannelMerger,
69bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        NodeTypeAnalyser,
70bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        NodeTypeEnd
71bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    };
72bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
73bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    NodeType type() const { return m_type; }
74bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    void setType(NodeType);
75bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
76bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // We handle our own ref-counting because of the threading issues and subtle nature of
77bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // how AudioNodes can continue processing (playing one-shot sound) after there are no more
78bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // JavaScript references to the object.
79bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    enum RefType { RefTypeNormal, RefTypeConnection, RefTypeDisabled };
80bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
81bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Can be called from main thread or context's audio thread.
82bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    void ref(RefType refType = RefTypeNormal);
83bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    void deref(RefType refType = RefTypeNormal);
84bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
85bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Can be called from main thread or context's audio thread.  It must be called while the context's graph lock is held.
86bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    void finishDeref(RefType refType);
87bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
88bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // The AudioNodeInput(s) (if any) will already have their input data available when process() is called.
89bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Subclasses will take this input data and put the results in the AudioBus(s) of its AudioNodeOutput(s) (if any).
90bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Called from context's audio thread.
91bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    virtual void process(size_t framesToProcess) = 0;
92bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
93bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Resets DSP processing state (clears delay lines, filter memory, etc.)
94bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Called from context's audio thread.
95bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    virtual void reset() = 0;
96bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
97bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // No significant resources should be allocated until initialize() is called.
98bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Processing may not occur until a node is initialized.
99a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    virtual void initialize();
100a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    virtual void uninitialize();
101bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
102bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    bool isInitialized() const { return m_isInitialized; }
103bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    void lazyInitialize();
104bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
105bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    unsigned numberOfInputs() const { return m_inputs.size(); }
106bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    unsigned numberOfOutputs() const { return m_outputs.size(); }
107bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
108bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    AudioNodeInput* input(unsigned);
109bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    AudioNodeOutput* output(unsigned);
110bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
111bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // connect() / disconnect() return true on success.
112bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Called from main thread by corresponding JavaScript methods.
113bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    bool connect(AudioNode* destination, unsigned outputIndex = 0, unsigned inputIndex = 0);
114bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    bool disconnect(unsigned outputIndex = 0);
115bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
116bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    double sampleRate() const { return m_sampleRate; }
117bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
118bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // processIfNecessary() is called by our output(s) when the rendering graph needs this AudioNode to process.
119bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // This method ensures that the AudioNode will only process once per rendering time quantum even if it's called repeatedly.
120bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // This handles the case of "fanout" where an output is connected to multiple AudioNode inputs.
121bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Called from context's audio thread.
122bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    void processIfNecessary(size_t framesToProcess);
123bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
124bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Called when a new connection has been made to one of our inputs or the connection number of channels has changed.
125bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // This potentially gives us enough information to perform a lazy initialization or, if necessary, a re-initialization.
126bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Called from main thread.
127bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    virtual void checkNumberOfChannelsForInput(AudioNodeInput*) { }
128bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
129bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#if DEBUG_AUDIONODE_REFERENCES
130bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    static void printNodeCounts();
131bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#endif
132bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
133e14391e94c850b8bd03680c23b38978db68687a8John Reck    bool isMarkedForDeletion() const { return m_isMarkedForDeletion; }
134e14391e94c850b8bd03680c23b38978db68687a8John Reck
135bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenprotected:
136bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Inputs and outputs must be created before the AudioNode is initialized.
137bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    void addInput(PassOwnPtr<AudioNodeInput>);
138bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    void addOutput(PassOwnPtr<AudioNodeOutput>);
139bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
140bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Called by processIfNecessary() to cause all parts of the rendering graph connected to us to process.
141bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Each rendering quantum, the audio data for each of the AudioNode's inputs will be available after this method is called.
142bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Called from context's audio thread.
143bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    virtual void pullInputs(size_t framesToProcess);
144bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
145bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenprivate:
146a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    volatile bool m_isInitialized;
147bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    NodeType m_type;
148bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    RefPtr<AudioContext> m_context;
149bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    double m_sampleRate;
150bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    Vector<OwnPtr<AudioNodeInput> > m_inputs;
151bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    Vector<OwnPtr<AudioNodeOutput> > m_outputs;
152bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
153bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    double m_lastProcessingTime;
154bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
155bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Ref-counting
156bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    volatile int m_normalRefCount;
157bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    volatile int m_connectionRefCount;
158bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    volatile int m_disabledRefCount;
159bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
160bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    bool m_isMarkedForDeletion;
161bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    bool m_isDisabled;
162bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
163bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#if DEBUG_AUDIONODE_REFERENCES
164bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    static bool s_isNodeCountInitialized;
165bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    static int s_nodeCount[NodeTypeEnd];
166bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#endif
167bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen};
168bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
169bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen} // namespace WebCore
170bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
171bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#endif // AudioNode_h
172