Unreviewed, rolling out r218373.
[WebKit-https.git] / Source / WebCore / Modules / webaudio / AudioNode.cpp
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 #include "config.h"
26
27 #if ENABLE(WEB_AUDIO)
28
29 #include "AudioNode.h"
30
31 #include "AudioContext.h"
32 #include "AudioNodeInput.h"
33 #include "AudioNodeOutput.h"
34 #include "AudioParam.h"
35 #include "ExceptionCode.h"
36 #include <wtf/Atomics.h>
37 #include <wtf/MainThread.h>
38
39 #if DEBUG_AUDIONODE_REFERENCES
40 #include <stdio.h>
41 #endif
42
43 namespace WebCore {
44
45 AudioNode::AudioNode(AudioContext& context, float sampleRate)
46     : m_isInitialized(false)
47     , m_nodeType(NodeTypeUnknown)
48     , m_context(context)
49     , m_sampleRate(sampleRate)
50     , m_lastProcessingTime(-1)
51     , m_lastNonSilentTime(-1)
52     , m_normalRefCount(1) // start out with normal refCount == 1 (like WTF::RefCounted class)
53     , m_connectionRefCount(0)
54     , m_isMarkedForDeletion(false)
55     , m_isDisabled(false)
56     , m_channelCount(2)
57     , m_channelCountMode(Max)
58     , m_channelInterpretation(AudioBus::Speakers)
59 {
60 #if DEBUG_AUDIONODE_REFERENCES
61     if (!s_isNodeCountInitialized) {
62         s_isNodeCountInitialized = true;
63         atexit(AudioNode::printNodeCounts);
64     }
65 #endif
66 }
67
68 AudioNode::~AudioNode()
69 {
70     ASSERT(isMainThread());
71 #if DEBUG_AUDIONODE_REFERENCES
72     --s_nodeCount[nodeType()];
73     fprintf(stderr, "%p: %d: AudioNode::~AudioNode() %d %d\n", this, nodeType(), m_normalRefCount.load(), m_connectionRefCount);
74 #endif
75 }
76
77 void AudioNode::initialize()
78 {
79     m_isInitialized = true;
80 }
81
82 void AudioNode::uninitialize()
83 {
84     m_isInitialized = false;
85 }
86
87 void AudioNode::setNodeType(NodeType type)
88 {
89     m_nodeType = type;
90
91 #if DEBUG_AUDIONODE_REFERENCES
92     ++s_nodeCount[type];
93 #endif
94 }
95
96 void AudioNode::lazyInitialize()
97 {
98     if (!isInitialized())
99         initialize();
100 }
101
102 void AudioNode::addInput(std::unique_ptr<AudioNodeInput> input)
103 {
104     m_inputs.append(WTFMove(input));
105 }
106
107 void AudioNode::addOutput(std::unique_ptr<AudioNodeOutput> output)
108 {
109     m_outputs.append(WTFMove(output));
110 }
111
112 AudioNodeInput* AudioNode::input(unsigned i)
113 {
114     if (i < m_inputs.size())
115         return m_inputs[i].get();
116     return nullptr;
117 }
118
119 AudioNodeOutput* AudioNode::output(unsigned i)
120 {
121     if (i < m_outputs.size())
122         return m_outputs[i].get();
123     return nullptr;
124 }
125
126 ExceptionOr<void> AudioNode::connect(AudioNode& destination, unsigned outputIndex, unsigned inputIndex)
127 {
128     ASSERT(isMainThread()); 
129     AudioContext::AutoLocker locker(context());
130
131     // Sanity check input and output indices.
132     if (outputIndex >= numberOfOutputs())
133         return Exception { INDEX_SIZE_ERR };
134
135     if (inputIndex >= destination.numberOfInputs())
136         return Exception { INDEX_SIZE_ERR };
137
138     if (context() != destination.context())
139         return Exception { SYNTAX_ERR };
140
141     auto* input = destination.input(inputIndex);
142     auto* output = this->output(outputIndex);
143     input->connect(output);
144
145     // Let context know that a connection has been made.
146     context().incrementConnectionCount();
147
148     return { };
149 }
150
151 ExceptionOr<void> AudioNode::connect(AudioParam& param, unsigned outputIndex)
152 {
153     ASSERT(isMainThread());
154     AudioContext::AutoLocker locker(context());
155
156     if (outputIndex >= numberOfOutputs())
157         return Exception { INDEX_SIZE_ERR };
158
159     if (context() != param.context())
160         return Exception { SYNTAX_ERR };
161
162     auto* output = this->output(outputIndex);
163     param.connect(output);
164
165     return { };
166 }
167
168 ExceptionOr<void> AudioNode::disconnect(unsigned outputIndex)
169 {
170     ASSERT(isMainThread());
171     AudioContext::AutoLocker locker(context());
172
173     // Sanity check input and output indices.
174     if (outputIndex >= numberOfOutputs())
175         return Exception { INDEX_SIZE_ERR };
176
177     auto* output = this->output(outputIndex);
178     output->disconnectAll();
179
180     return { };
181 }
182
183 unsigned AudioNode::channelCount()
184 {
185     return m_channelCount;
186 }
187
188 ExceptionOr<void> AudioNode::setChannelCount(unsigned channelCount)
189 {
190     ASSERT(isMainThread());
191     AudioContext::AutoLocker locker(context());
192
193     if (!(channelCount > 0 && channelCount <= AudioContext::maxNumberOfChannels()))
194         return Exception { INVALID_STATE_ERR };
195
196     if (m_channelCount == channelCount)
197         return { };
198
199     m_channelCount = channelCount;
200     if (m_channelCountMode != Max)
201         updateChannelsForInputs();
202     return { };
203 }
204
205 String AudioNode::channelCountMode()
206 {
207     switch (m_channelCountMode) {
208     case Max:
209         return ASCIILiteral("max");
210     case ClampedMax:
211         return ASCIILiteral("clamped-max");
212     case Explicit:
213         return ASCIILiteral("explicit");
214     }
215     ASSERT_NOT_REACHED();
216     return emptyString();
217 }
218
219 ExceptionOr<void> AudioNode::setChannelCountMode(const String& mode)
220 {
221     ASSERT(isMainThread());
222     AudioContext::AutoLocker locker(context());
223
224     ChannelCountMode oldMode = m_channelCountMode;
225
226     if (mode == "max")
227         m_channelCountMode = Max;
228     else if (mode == "clamped-max")
229         m_channelCountMode = ClampedMax;
230     else if (mode == "explicit")
231         m_channelCountMode = Explicit;
232     else
233         return Exception { INVALID_STATE_ERR };
234
235     if (m_channelCountMode != oldMode)
236         updateChannelsForInputs();
237
238     return { };
239 }
240
241 String AudioNode::channelInterpretation()
242 {
243     switch (m_channelInterpretation) {
244     case AudioBus::Speakers:
245         return ASCIILiteral("speakers");
246     case AudioBus::Discrete:
247         return ASCIILiteral("discrete");
248     }
249     ASSERT_NOT_REACHED();
250     return emptyString();
251 }
252
253 ExceptionOr<void> AudioNode::setChannelInterpretation(const String& interpretation)
254 {
255     ASSERT(isMainThread());
256     AudioContext::AutoLocker locker(context());
257
258     if (interpretation == "speakers")
259         m_channelInterpretation = AudioBus::Speakers;
260     else if (interpretation == "discrete")
261         m_channelInterpretation = AudioBus::Discrete;
262     else
263         return Exception { INVALID_STATE_ERR };
264
265     return { };
266 }
267
268 void AudioNode::updateChannelsForInputs()
269 {
270     for (auto& input : m_inputs)
271         input->changedOutputs();
272 }
273
274 EventTargetInterface AudioNode::eventTargetInterface() const
275 {
276     return AudioNodeEventTargetInterfaceType;
277 }
278
279 ScriptExecutionContext* AudioNode::scriptExecutionContext() const
280 {
281     return const_cast<AudioNode*>(this)->context().scriptExecutionContext();
282 }
283
284 void AudioNode::processIfNecessary(size_t framesToProcess)
285 {
286     ASSERT(context().isAudioThread());
287
288     if (!isInitialized())
289         return;
290
291     // Ensure that we only process once per rendering quantum.
292     // This handles the "fanout" problem where an output is connected to multiple inputs.
293     // The first time we're called during this time slice we process, but after that we don't want to re-process,
294     // instead our output(s) will already have the results cached in their bus;
295     double currentTime = context().currentTime();
296     if (m_lastProcessingTime != currentTime) {
297         m_lastProcessingTime = currentTime; // important to first update this time because of feedback loops in the rendering graph
298
299         pullInputs(framesToProcess);
300
301         bool silentInputs = inputsAreSilent();
302         if (!silentInputs)
303             m_lastNonSilentTime = (context().currentSampleFrame() + framesToProcess) / static_cast<double>(m_sampleRate);
304
305         if (silentInputs && propagatesSilence())
306             silenceOutputs();
307         else
308             process(framesToProcess);
309     }
310 }
311
312 void AudioNode::checkNumberOfChannelsForInput(AudioNodeInput* input)
313 {
314     ASSERT(context().isAudioThread() && context().isGraphOwner());
315
316     for (auto& savedInput : m_inputs) {
317         if (input == savedInput.get()) {
318             input->updateInternalBus();
319             return;
320         }
321     }
322
323     ASSERT_NOT_REACHED();
324 }
325
326 bool AudioNode::propagatesSilence() const
327 {
328     return m_lastNonSilentTime + latencyTime() + tailTime() < context().currentTime();
329 }
330
331 void AudioNode::pullInputs(size_t framesToProcess)
332 {
333     ASSERT(context().isAudioThread());
334     
335     // Process all of the AudioNodes connected to our inputs.
336     for (auto& input : m_inputs)
337         input->pull(0, framesToProcess);
338 }
339
340 bool AudioNode::inputsAreSilent()
341 {
342     for (auto& input : m_inputs) {
343         if (!input->bus()->isSilent())
344             return false;
345     }
346     return true;
347 }
348
349 void AudioNode::silenceOutputs()
350 {
351     for (auto& output : m_outputs)
352         output->bus()->zero();
353 }
354
355 void AudioNode::enableOutputsIfNecessary()
356 {
357     if (m_isDisabled && m_connectionRefCount > 0) {
358         ASSERT(isMainThread());
359         AudioContext::AutoLocker locker(context());
360
361         m_isDisabled = false;
362         for (auto& output : m_outputs)
363             output->enable();
364     }
365 }
366
367 void AudioNode::disableOutputsIfNecessary()
368 {
369     // Disable outputs if appropriate. We do this if the number of connections is 0 or 1. The case
370     // of 0 is from finishDeref() where there are no connections left. The case of 1 is from
371     // AudioNodeInput::disable() where we want to disable outputs when there's only one connection
372     // left because we're ready to go away, but can't quite yet.
373     if (m_connectionRefCount <= 1 && !m_isDisabled) {
374         // Still may have JavaScript references, but no more "active" connection references, so put all of our outputs in a "dormant" disabled state.
375         // Garbage collection may take a very long time after this time, so the "dormant" disabled nodes should not bog down the rendering...
376
377         // As far as JavaScript is concerned, our outputs must still appear to be connected.
378         // But internally our outputs should be disabled from the inputs they're connected to.
379         // disable() can recursively deref connections (and call disable()) down a whole chain of connected nodes.
380
381         // FIXME: we special case the convolver and delay since they have a significant tail-time and shouldn't be disconnected simply
382         // because they no longer have any input connections. This needs to be handled more generally where AudioNodes have
383         // a tailTime attribute. Then the AudioNode only needs to remain "active" for tailTime seconds after there are no
384         // longer any active connections.
385         if (nodeType() != NodeTypeConvolver && nodeType() != NodeTypeDelay) {
386             m_isDisabled = true;
387             for (auto& output : m_outputs)
388                 output->disable();
389         }
390     }
391 }
392
393 void AudioNode::ref(RefType refType)
394 {
395     switch (refType) {
396     case RefTypeNormal:
397         ++m_normalRefCount;
398         break;
399     case RefTypeConnection:
400         ++m_connectionRefCount;
401         break;
402     default:
403         ASSERT_NOT_REACHED();
404     }
405
406 #if DEBUG_AUDIONODE_REFERENCES
407     fprintf(stderr, "%p: %d: AudioNode::ref(%d) %d %d\n", this, nodeType(), refType, m_normalRefCount, m_connectionRefCount);
408 #endif
409
410     // See the disabling code in finishDeref() below. This handles the case where a node
411     // is being re-connected after being used at least once and disconnected.
412     // In this case, we need to re-enable.
413     if (refType == RefTypeConnection)
414         enableOutputsIfNecessary();
415 }
416
417 void AudioNode::deref(RefType refType)
418 {
419     // The actually work for deref happens completely within the audio context's graph lock.
420     // In the case of the audio thread, we must use a tryLock to avoid glitches.
421     bool hasLock = false;
422     bool mustReleaseLock = false;
423     
424     if (context().isAudioThread()) {
425         // Real-time audio thread must not contend lock (to avoid glitches).
426         hasLock = context().tryLock(mustReleaseLock);
427     } else {
428         context().lock(mustReleaseLock);
429         hasLock = true;
430     }
431     
432     if (hasLock) {
433         // This is where the real deref work happens.
434         finishDeref(refType);
435
436         if (mustReleaseLock)
437             context().unlock();
438     } else {
439         // We were unable to get the lock, so put this in a list to finish up later.
440         ASSERT(context().isAudioThread());
441         ASSERT(refType == RefTypeConnection);
442         context().addDeferredFinishDeref(this);
443     }
444
445     // Once AudioContext::uninitialize() is called there's no more chances for deleteMarkedNodes() to get called, so we call here.
446     // We can't call in AudioContext::~AudioContext() since it will never be called as long as any AudioNode is alive
447     // because AudioNodes keep a reference to the context.
448     if (context().isAudioThreadFinished())
449         context().deleteMarkedNodes();
450 }
451
452 void AudioNode::finishDeref(RefType refType)
453 {
454     ASSERT(context().isGraphOwner());
455     
456     switch (refType) {
457     case RefTypeNormal:
458         ASSERT(m_normalRefCount > 0);
459         --m_normalRefCount;
460         break;
461     case RefTypeConnection:
462         ASSERT(m_connectionRefCount > 0);
463         --m_connectionRefCount;
464         break;
465     default:
466         ASSERT_NOT_REACHED();
467     }
468     
469 #if DEBUG_AUDIONODE_REFERENCES
470     fprintf(stderr, "%p: %d: AudioNode::deref(%d) %d %d\n", this, nodeType(), refType, m_normalRefCount, m_connectionRefCount);
471 #endif
472
473     if (!m_connectionRefCount) {
474         if (!m_normalRefCount) {
475             if (!m_isMarkedForDeletion) {
476                 // All references are gone - we need to go away.
477                 for (auto& output : m_outputs)
478                     output->disconnectAll(); // This will deref() nodes we're connected to.
479
480                 // Mark for deletion at end of each render quantum or when context shuts down.
481                 context().markForDeletion(this);
482                 m_isMarkedForDeletion = true;
483             }
484         } else if (refType == RefTypeConnection)
485             disableOutputsIfNecessary();
486     }
487 }
488
489 #if DEBUG_AUDIONODE_REFERENCES
490
491 bool AudioNode::s_isNodeCountInitialized = false;
492 int AudioNode::s_nodeCount[NodeTypeEnd];
493
494 void AudioNode::printNodeCounts()
495 {
496     fprintf(stderr, "\n\n");
497     fprintf(stderr, "===========================\n");
498     fprintf(stderr, "AudioNode: reference counts\n");
499     fprintf(stderr, "===========================\n");
500
501     for (unsigned i = 0; i < NodeTypeEnd; ++i)
502         fprintf(stderr, "%d: %d\n", i, s_nodeCount[i]);
503
504     fprintf(stderr, "===========================\n\n\n");
505 }
506
507 #endif // DEBUG_AUDIONODE_REFERENCES
508
509 } // namespace WebCore
510
511 #endif // ENABLE(WEB_AUDIO)