4513f7d86586cb76cd2f3e43b2cfd61339824411
[WebKit-https.git] / Source / WebCore / Modules / webaudio / AudioDestinationNode.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 "AudioDestinationNode.h"
30
31 #include "AudioContext.h"
32 #include "AudioNodeInput.h"
33 #include "AudioNodeOutput.h"
34 #include "AudioUtilities.h"
35 #include "AudioWorklet.h"
36 #include "AudioWorkletGlobalScope.h"
37 #include "AudioWorkletMessagingProxy.h"
38 #include "AudioWorkletThread.h"
39 #include "DenormalDisabler.h"
40 #include <wtf/IsoMallocInlines.h>
41
42 namespace WebCore {
43     
44 WTF_MAKE_ISO_ALLOCATED_IMPL(AudioDestinationNode);
45
46 AudioDestinationNode::AudioDestinationNode(BaseAudioContext& context, float sampleRate)
47     : AudioNode(context, NodeTypeDestination)
48     , m_sampleRate(sampleRate)
49 {
50     addInput();
51 }
52
53 AudioDestinationNode::~AudioDestinationNode()
54 {
55     uninitialize();
56 }
57
58 void AudioDestinationNode::render(AudioBus*, AudioBus* destinationBus, size_t numberOfFrames, const AudioIOPosition& outputPosition)
59 {
60     // We don't want denormals slowing down any of the audio processing
61     // since they can very seriously hurt performance.
62     // This will take care of all AudioNodes because they all process within this scope.
63     DenormalDisabler denormalDisabler;
64     
65     context().setAudioThread(Thread::current());
66
67     // For performance reasons, we forbid heap allocations while doing rendering on the audio thread.
68     // Heap allocations that cannot be avoided or have not been fixed yet can be allowed using
69     // DisableMallocRestrictionsForCurrentThreadScope scope variables.
70     ForbidMallocUseForCurrentThreadScope forbidMallocUse;
71     
72     if (!context().isInitialized()) {
73         destinationBus->zero();
74         setIsSilent(true);
75         return;
76     }
77
78     ASSERT(numberOfFrames);
79     if (!numberOfFrames) {
80         destinationBus->zero();
81         setIsSilent(true);
82         return;
83     }
84
85     // Let the context take care of any business at the start of each render quantum.
86     context().handlePreRenderTasks(outputPosition);
87
88     RefPtr<AudioWorkletGlobalScope> workletGlobalScope;
89     if (auto* audioWorkletProxy = context().audioWorklet().proxy())
90         workletGlobalScope = audioWorkletProxy->workletThread().globalScope();
91     if (workletGlobalScope)
92         workletGlobalScope->handlePreRenderTasks();
93
94     // This will cause the node(s) connected to us to process, which in turn will pull on their input(s),
95     // all the way backwards through the rendering graph.
96     AudioBus* renderedBus = input(0)->pull(destinationBus, numberOfFrames);
97
98     if (!renderedBus)
99         destinationBus->zero();
100     else if (renderedBus != destinationBus) {
101         // in-place processing was not possible - so copy
102         destinationBus->copyFrom(*renderedBus);
103     }
104
105     // Process nodes which need a little extra help because they are not connected to anything, but still need to process.
106     context().processAutomaticPullNodes(numberOfFrames);
107
108     // Let the context take care of any business at the end of each render quantum.
109     context().handlePostRenderTasks();
110     
111     // Advance current sample-frame.
112     m_currentSampleFrame += numberOfFrames;
113
114     if (workletGlobalScope)
115         workletGlobalScope->handlePostRenderTasks(m_currentSampleFrame);
116
117     setIsSilent(destinationBus->isSilent());
118
119     // The reason we are handling mute after the call to setIsSilent() is because the muted state does
120     // not affect the audio destination node's effective playing state.
121     if (m_muted)
122         destinationBus->zero();
123 }
124
125 void AudioDestinationNode::isPlayingDidChange()
126 {
127     updateIsEffectivelyPlayingAudio();
128 }
129
130 void AudioDestinationNode::setIsSilent(bool isSilent)
131 {
132     if (m_isSilent == isSilent)
133         return;
134
135     m_isSilent = isSilent;
136     updateIsEffectivelyPlayingAudio();
137 }
138
139 void AudioDestinationNode::updateIsEffectivelyPlayingAudio()
140 {
141     bool isEffectivelyPlayingAudio = isPlaying() && !m_isSilent;
142     if (m_isEffectivelyPlayingAudio == isEffectivelyPlayingAudio)
143         return;
144
145     m_isEffectivelyPlayingAudio = isEffectivelyPlayingAudio;
146     context().isPlayingAudioDidChange();
147 }
148
149 void AudioDestinationNode::ref()
150 {
151     context().ref();
152 }
153
154 void AudioDestinationNode::deref()
155 {
156     context().deref();
157 }
158
159 } // namespace WebCore
160
161 #endif // ENABLE(WEB_AUDIO)