Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / 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 "modules/webaudio/AudioNode.h"
30
31 #include "bindings/core/v8/ExceptionState.h"
32 #include "core/dom/ExceptionCode.h"
33 #include "modules/webaudio/AudioContext.h"
34 #include "modules/webaudio/AudioNodeInput.h"
35 #include "modules/webaudio/AudioNodeOutput.h"
36 #include "modules/webaudio/AudioParam.h"
37 #include "wtf/Atomics.h"
38 #include "wtf/MainThread.h"
39
40 #if DEBUG_AUDIONODE_REFERENCES
41 #include <stdio.h>
42 #endif
43
44 namespace blink {
45
46 unsigned AudioNode::s_instanceCount = 0;
47
48 AudioNode::AudioNode(AudioContext* context, float sampleRate)
49     : m_isInitialized(false)
50     , m_nodeType(NodeTypeUnknown)
51     , m_context(context)
52     , m_sampleRate(sampleRate)
53     , m_lastProcessingTime(-1)
54     , m_lastNonSilentTime(-1)
55     , m_connectionRefCount(0)
56     , m_isDisabled(false)
57     , m_channelCount(2)
58     , m_channelCountMode(Max)
59     , m_channelInterpretation(AudioBus::Speakers)
60     , m_newChannelCountMode(Max)
61 {
62     m_context->registerLiveNode(*this);
63 #if DEBUG_AUDIONODE_REFERENCES
64     if (!s_isNodeCountInitialized) {
65         s_isNodeCountInitialized = true;
66         atexit(AudioNode::printNodeCounts);
67     }
68 #endif
69     ++s_instanceCount;
70 }
71
72 AudioNode::~AudioNode()
73 {
74     --s_instanceCount;
75 #if DEBUG_AUDIONODE_REFERENCES
76     --s_nodeCount[nodeType()];
77     fprintf(stderr, "%p: %2d: AudioNode::~AudioNode() %d [%d]\n",
78         this, nodeType(), m_connectionRefCount, s_nodeCount[nodeType()]);
79 #endif
80 }
81
82 void AudioNode::initialize()
83 {
84     m_isInitialized = true;
85 }
86
87 void AudioNode::uninitialize()
88 {
89     m_isInitialized = false;
90 }
91
92 void AudioNode::clearInternalStateWhenDisabled()
93 {
94 }
95
96 void AudioNode::dispose()
97 {
98     ASSERT(isMainThread());
99     ASSERT(context()->isGraphOwner());
100
101     context()->removeChangedChannelCountMode(this);
102     context()->removeAutomaticPullNode(this);
103     context()->disposeOutputs(*this);
104     for (unsigned i = 0; i < m_outputs.size(); ++i)
105         output(i)->disconnectAll();
106 }
107
108 String AudioNode::nodeTypeName() const
109 {
110     switch (m_nodeType) {
111     case NodeTypeDestination:
112         return "AudioDestinationNode";
113     case NodeTypeOscillator:
114         return "OscillatorNode";
115     case NodeTypeAudioBufferSource:
116         return "AudioBufferSourceNode";
117     case NodeTypeMediaElementAudioSource:
118         return "MediaElementAudioSourceNode";
119     case NodeTypeMediaStreamAudioDestination:
120         return "MediaStreamAudioDestinationNode";
121     case NodeTypeMediaStreamAudioSource:
122         return "MediaStreamAudioSourceNode";
123     case NodeTypeJavaScript:
124         return "ScriptProcessorNode";
125     case NodeTypeBiquadFilter:
126         return "BiquadFilterNode";
127     case NodeTypePanner:
128         return "PannerNode";
129     case NodeTypeConvolver:
130         return "ConvolverNode";
131     case NodeTypeDelay:
132         return "DelayNode";
133     case NodeTypeGain:
134         return "GainNode";
135     case NodeTypeChannelSplitter:
136         return "ChannelSplitterNode";
137     case NodeTypeChannelMerger:
138         return "ChannelMergerNode";
139     case NodeTypeAnalyser:
140         return "AnalyserNode";
141     case NodeTypeDynamicsCompressor:
142         return "DynamicsCompressorNode";
143     case NodeTypeWaveShaper:
144         return "WaveShaperNode";
145     case NodeTypeUnknown:
146     case NodeTypeEnd:
147     default:
148         ASSERT_NOT_REACHED();
149         return "UnknownNode";
150     }
151 }
152
153 void AudioNode::setNodeType(NodeType type)
154 {
155     m_nodeType = type;
156
157 #if DEBUG_AUDIONODE_REFERENCES
158     ++s_nodeCount[type];
159     fprintf(stderr, "%p: %2d: AudioNode::AudioNode [%3d]\n", this, nodeType(), s_nodeCount[nodeType()]);
160 #endif
161 }
162
163 void AudioNode::addInput()
164 {
165     m_inputs.append(AudioNodeInput::create(*this));
166 }
167
168 void AudioNode::addOutput(AudioNodeOutput* output)
169 {
170     m_outputs.append(output);
171 }
172
173 AudioNodeInput* AudioNode::input(unsigned i)
174 {
175     if (i < m_inputs.size())
176         return m_inputs[i].get();
177     return 0;
178 }
179
180 AudioNodeOutput* AudioNode::output(unsigned i)
181 {
182     if (i < m_outputs.size())
183         return m_outputs[i].get();
184     return 0;
185 }
186
187 void AudioNode::connect(AudioNode* destination, unsigned outputIndex, unsigned inputIndex, ExceptionState& exceptionState)
188 {
189     ASSERT(isMainThread());
190     AudioContext::AutoLocker locker(context());
191
192     if (!destination) {
193         exceptionState.throwDOMException(
194             SyntaxError,
195             "invalid destination node.");
196         return;
197     }
198
199     // Sanity check input and output indices.
200     if (outputIndex >= numberOfOutputs()) {
201         exceptionState.throwDOMException(
202             IndexSizeError,
203             "output index (" + String::number(outputIndex) + ") exceeds number of outputs (" + String::number(numberOfOutputs()) + ").");
204         return;
205     }
206
207     if (destination && inputIndex >= destination->numberOfInputs()) {
208         exceptionState.throwDOMException(
209             IndexSizeError,
210             "input index (" + String::number(inputIndex) + ") exceeds number of inputs (" + String::number(destination->numberOfInputs()) + ").");
211         return;
212     }
213
214     if (context() != destination->context()) {
215         exceptionState.throwDOMException(
216             SyntaxError,
217             "cannot connect to a destination belonging to a different audio context.");
218         return;
219     }
220
221     AudioNodeInput* input = destination->input(inputIndex);
222     input->connect(*output(outputIndex));
223
224     // Let context know that a connection has been made.
225     context()->incrementConnectionCount();
226 }
227
228 void AudioNode::connect(AudioParam* param, unsigned outputIndex, ExceptionState& exceptionState)
229 {
230     ASSERT(isMainThread());
231     AudioContext::AutoLocker locker(context());
232
233     if (!param) {
234         exceptionState.throwDOMException(
235             SyntaxError,
236             "invalid AudioParam.");
237         return;
238     }
239
240     if (outputIndex >= numberOfOutputs()) {
241         exceptionState.throwDOMException(
242             IndexSizeError,
243             "output index (" + String::number(outputIndex) + ") exceeds number of outputs (" + String::number(numberOfOutputs()) + ").");
244         return;
245     }
246
247     if (context() != param->context()) {
248         exceptionState.throwDOMException(
249             SyntaxError,
250             "cannot connect to an AudioParam belonging to a different audio context.");
251         return;
252     }
253
254     param->connect(*output(outputIndex));
255 }
256
257 void AudioNode::disconnect(unsigned outputIndex, ExceptionState& exceptionState)
258 {
259     ASSERT(isMainThread());
260     AudioContext::AutoLocker locker(context());
261
262     // Sanity check input and output indices.
263     if (outputIndex >= numberOfOutputs()) {
264         exceptionState.throwDOMException(
265             IndexSizeError,
266             "output index (" + String::number(outputIndex) + ") exceeds number of outputs (" + String::number(numberOfOutputs()) + ").");
267         return;
268     }
269
270     AudioNodeOutput* output = this->output(outputIndex);
271     output->disconnectAll();
272 }
273
274 unsigned long AudioNode::channelCount()
275 {
276     return m_channelCount;
277 }
278
279 void AudioNode::setChannelCount(unsigned long channelCount, ExceptionState& exceptionState)
280 {
281     ASSERT(isMainThread());
282     AudioContext::AutoLocker locker(context());
283
284     if (channelCount > 0 && channelCount <= AudioContext::maxNumberOfChannels()) {
285         if (m_channelCount != channelCount) {
286             m_channelCount = channelCount;
287             if (m_channelCountMode != Max)
288                 updateChannelsForInputs();
289         }
290     } else {
291         exceptionState.throwDOMException(
292             NotSupportedError,
293             "channel count (" + String::number(channelCount) + ") must be between 1 and " + String::number(AudioContext::maxNumberOfChannels()) + ".");
294     }
295 }
296
297 String AudioNode::channelCountMode()
298 {
299     switch (m_channelCountMode) {
300     case Max:
301         return "max";
302     case ClampedMax:
303         return "clamped-max";
304     case Explicit:
305         return "explicit";
306     }
307     ASSERT_NOT_REACHED();
308     return "";
309 }
310
311 void AudioNode::setChannelCountMode(const String& mode, ExceptionState& exceptionState)
312 {
313     ASSERT(isMainThread());
314     AudioContext::AutoLocker locker(context());
315
316     ChannelCountMode oldMode = m_channelCountMode;
317
318     if (mode == "max") {
319         m_newChannelCountMode = Max;
320     } else if (mode == "clamped-max") {
321         m_newChannelCountMode = ClampedMax;
322     } else if (mode == "explicit") {
323         m_newChannelCountMode = Explicit;
324     } else {
325         ASSERT_NOT_REACHED();
326     }
327
328     if (m_newChannelCountMode != oldMode)
329         context()->addChangedChannelCountMode(this);
330 }
331
332 String AudioNode::channelInterpretation()
333 {
334     switch (m_channelInterpretation) {
335     case AudioBus::Speakers:
336         return "speakers";
337     case AudioBus::Discrete:
338         return "discrete";
339     }
340     ASSERT_NOT_REACHED();
341     return "";
342 }
343
344 void AudioNode::setChannelInterpretation(const String& interpretation, ExceptionState& exceptionState)
345 {
346     ASSERT(isMainThread());
347     AudioContext::AutoLocker locker(context());
348
349     if (interpretation == "speakers") {
350         m_channelInterpretation = AudioBus::Speakers;
351     } else if (interpretation == "discrete") {
352         m_channelInterpretation = AudioBus::Discrete;
353     } else {
354         ASSERT_NOT_REACHED();
355     }
356 }
357
358 void AudioNode::updateChannelsForInputs()
359 {
360     for (unsigned i = 0; i < m_inputs.size(); ++i)
361         input(i)->changedOutputs();
362 }
363
364 const AtomicString& AudioNode::interfaceName() const
365 {
366     return EventTargetNames::AudioNode;
367 }
368
369 ExecutionContext* AudioNode::executionContext() const
370 {
371     return const_cast<AudioNode*>(this)->context()->executionContext();
372 }
373
374 void AudioNode::processIfNecessary(size_t framesToProcess)
375 {
376     ASSERT(context()->isAudioThread());
377
378     if (!isInitialized())
379         return;
380
381     // Ensure that we only process once per rendering quantum.
382     // This handles the "fanout" problem where an output is connected to multiple inputs.
383     // The first time we're called during this time slice we process, but after that we don't want to re-process,
384     // instead our output(s) will already have the results cached in their bus;
385     double currentTime = context()->currentTime();
386     if (m_lastProcessingTime != currentTime) {
387         m_lastProcessingTime = currentTime; // important to first update this time because of feedback loops in the rendering graph
388
389         pullInputs(framesToProcess);
390
391         bool silentInputs = inputsAreSilent();
392         if (!silentInputs)
393             m_lastNonSilentTime = (context()->currentSampleFrame() + framesToProcess) / static_cast<double>(m_sampleRate);
394
395         if (silentInputs && propagatesSilence())
396             silenceOutputs();
397         else {
398             process(framesToProcess);
399             unsilenceOutputs();
400         }
401     }
402 }
403
404 void AudioNode::checkNumberOfChannelsForInput(AudioNodeInput* input)
405 {
406     ASSERT(context()->isAudioThread() && context()->isGraphOwner());
407
408     ASSERT(m_inputs.contains(input));
409     if (!m_inputs.contains(input))
410         return;
411
412     input->updateInternalBus();
413 }
414
415 bool AudioNode::propagatesSilence() const
416 {
417     return m_lastNonSilentTime + latencyTime() + tailTime() < context()->currentTime();
418 }
419
420 void AudioNode::pullInputs(size_t framesToProcess)
421 {
422     ASSERT(context()->isAudioThread());
423
424     // Process all of the AudioNodes connected to our inputs.
425     for (unsigned i = 0; i < m_inputs.size(); ++i)
426         input(i)->pull(0, framesToProcess);
427 }
428
429 bool AudioNode::inputsAreSilent()
430 {
431     for (unsigned i = 0; i < m_inputs.size(); ++i) {
432         if (!input(i)->bus()->isSilent())
433             return false;
434     }
435     return true;
436 }
437
438 void AudioNode::silenceOutputs()
439 {
440     for (unsigned i = 0; i < m_outputs.size(); ++i)
441         output(i)->bus()->zero();
442 }
443
444 void AudioNode::unsilenceOutputs()
445 {
446     for (unsigned i = 0; i < m_outputs.size(); ++i)
447         output(i)->bus()->clearSilentFlag();
448 }
449
450 void AudioNode::enableOutputsIfNecessary()
451 {
452     if (m_isDisabled && m_connectionRefCount > 0) {
453         ASSERT(isMainThread());
454         AudioContext::AutoLocker locker(context());
455
456         m_isDisabled = false;
457         for (unsigned i = 0; i < m_outputs.size(); ++i)
458             output(i)->enable();
459     }
460 }
461
462 void AudioNode::disableOutputsIfNecessary()
463 {
464     // Disable outputs if appropriate. We do this if the number of connections is 0 or 1. The case
465     // of 0 is from deref() where there are no connections left. The case of 1 is from
466     // AudioNodeInput::disable() where we want to disable outputs when there's only one connection
467     // left because we're ready to go away, but can't quite yet.
468     if (m_connectionRefCount <= 1 && !m_isDisabled) {
469         // Still may have JavaScript references, but no more "active" connection references, so put all of our outputs in a "dormant" disabled state.
470         // Garbage collection may take a very long time after this time, so the "dormant" disabled nodes should not bog down the rendering...
471
472         // As far as JavaScript is concerned, our outputs must still appear to be connected.
473         // But internally our outputs should be disabled from the inputs they're connected to.
474         // disable() can recursively deref connections (and call disable()) down a whole chain of connected nodes.
475
476         // FIXME: we special case the convolver and delay since they have a significant tail-time and shouldn't be disconnected simply
477         // because they no longer have any input connections. This needs to be handled more generally where AudioNodes have
478         // a tailTime attribute. Then the AudioNode only needs to remain "active" for tailTime seconds after there are no
479         // longer any active connections.
480         if (nodeType() != NodeTypeConvolver && nodeType() != NodeTypeDelay) {
481             m_isDisabled = true;
482             clearInternalStateWhenDisabled();
483             for (unsigned i = 0; i < m_outputs.size(); ++i)
484                 output(i)->disable();
485         }
486     }
487 }
488
489 void AudioNode::makeConnection()
490 {
491     atomicIncrement(&m_connectionRefCount);
492
493 #if DEBUG_AUDIONODE_REFERENCES
494     fprintf(stderr, "%p: %2d: AudioNode::ref   %3d [%3d]\n",
495         this, nodeType(), m_connectionRefCount, s_nodeCount[nodeType()]);
496 #endif
497     // See the disabling code in disableOutputsIfNecessary(). This handles
498     // the case where a node is being re-connected after being used at least
499     // once and disconnected. In this case, we need to re-enable.
500     enableOutputsIfNecessary();
501 }
502
503 void AudioNode::breakConnection()
504 {
505     // The actual work for deref happens completely within the audio context's
506     // graph lock. In the case of the audio thread, we must use a tryLock to
507     // avoid glitches.
508     bool hasLock = false;
509     if (context()->isAudioThread()) {
510         // Real-time audio thread must not contend lock (to avoid glitches).
511         hasLock = context()->tryLock();
512     } else {
513         context()->lock();
514         hasLock = true;
515     }
516
517     if (hasLock) {
518         breakConnectionWithLock();
519         context()->unlock();
520     } else {
521         // We were unable to get the lock, so put this in a list to finish up
522         // later.
523         ASSERT(context()->isAudioThread());
524         context()->addDeferredBreakConnection(*this);
525     }
526 }
527
528 void AudioNode::breakConnectionWithLock()
529 {
530     atomicDecrement(&m_connectionRefCount);
531
532 #if DEBUG_AUDIONODE_REFERENCES
533     fprintf(stderr, "%p: %2d: AudioNode::deref %3d [%3d]\n",
534         this, nodeType(), m_connectionRefCount, s_nodeCount[nodeType()]);
535 #endif
536
537     if (!m_connectionRefCount)
538         disableOutputsIfNecessary();
539 }
540
541 #if DEBUG_AUDIONODE_REFERENCES
542
543 bool AudioNode::s_isNodeCountInitialized = false;
544 int AudioNode::s_nodeCount[NodeTypeEnd];
545
546 void AudioNode::printNodeCounts()
547 {
548     fprintf(stderr, "\n\n");
549     fprintf(stderr, "===========================\n");
550     fprintf(stderr, "AudioNode: reference counts\n");
551     fprintf(stderr, "===========================\n");
552
553     for (unsigned i = 0; i < NodeTypeEnd; ++i)
554         fprintf(stderr, "%2d: %d\n", i, s_nodeCount[i]);
555
556     fprintf(stderr, "===========================\n\n\n");
557 }
558
559 #endif // DEBUG_AUDIONODE_REFERENCES
560
561 void AudioNode::trace(Visitor* visitor)
562 {
563     visitor->trace(m_context);
564     visitor->trace(m_inputs);
565     visitor->trace(m_outputs);
566     EventTargetWithInlineData::trace(visitor);
567 }
568
569 void AudioNode::updateChannelCountMode()
570 {
571     m_channelCountMode = m_newChannelCountMode;
572     updateChannelsForInputs();
573 }
574
575 } // namespace blink
576
577 #endif // ENABLE(WEB_AUDIO)