Move more logic from AudioDestinationNode to its subclasses
[WebKit-https.git] / Source / WebCore / Modules / webaudio / AudioDestinationNode.cpp
1 /*
2  * Copyright (C) 2010, Google Inc. All rights reserved.
3  * Copyright (C) 2020-2021, Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1.  Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #if ENABLE(WEB_AUDIO)
29
30 #include "AudioDestinationNode.h"
31
32 #include "AudioBus.h"
33 #include "AudioContext.h"
34 #include "AudioIOCallback.h"
35 #include "AudioNodeInput.h"
36 #include "AudioNodeOutput.h"
37 #include "AudioUtilities.h"
38 #include "AudioWorklet.h"
39 #include "AudioWorkletGlobalScope.h"
40 #include "AudioWorkletMessagingProxy.h"
41 #include "AudioWorkletThread.h"
42 #include "DenormalDisabler.h"
43 #include <wtf/IsoMallocInlines.h>
44
45 namespace WebCore {
46     
47 WTF_MAKE_ISO_ALLOCATED_IMPL(AudioDestinationNode);
48
49 AudioDestinationNode::AudioDestinationNode(BaseAudioContext& context, float sampleRate)
50     : AudioNode(context, NodeTypeDestination)
51     , m_sampleRate(sampleRate)
52 {
53     addInput();
54 }
55
56 AudioDestinationNode::~AudioDestinationNode()
57 {
58     uninitialize();
59 }
60
61 void AudioDestinationNode::renderQuantum(AudioBus* destinationBus, size_t numberOfFrames, const AudioIOPosition& outputPosition)
62 {
63     // We don't want denormals slowing down any of the audio processing
64     // since they can very seriously hurt performance.
65     // This will take care of all AudioNodes because they all process within this scope.
66     DenormalDisabler denormalDisabler;
67     
68     context().setAudioThread(Thread::current());
69
70     // For performance reasons, we forbid heap allocations while doing rendering on the audio thread.
71     // Heap allocations that cannot be avoided or have not been fixed yet can be allowed using
72     // DisableMallocRestrictionsForCurrentThreadScope scope variables.
73     ForbidMallocUseForCurrentThreadScope forbidMallocUse;
74     
75     if (!context().isInitialized()) {
76         destinationBus->zero();
77         return;
78     }
79
80     ASSERT(numberOfFrames);
81     if (!numberOfFrames) {
82         destinationBus->zero();
83         return;
84     }
85
86     // Let the context take care of any business at the start of each render quantum.
87     context().handlePreRenderTasks(outputPosition);
88
89     RefPtr<AudioWorkletGlobalScope> workletGlobalScope;
90     if (auto* audioWorkletProxy = context().audioWorklet().proxy())
91         workletGlobalScope = audioWorkletProxy->workletThread().globalScope();
92     if (workletGlobalScope)
93         workletGlobalScope->handlePreRenderTasks();
94
95     // This will cause the node(s) connected to us to process, which in turn will pull on their input(s),
96     // all the way backwards through the rendering graph.
97     AudioBus* renderedBus = input(0)->pull(destinationBus, numberOfFrames);
98
99     if (!renderedBus)
100         destinationBus->zero();
101     else if (renderedBus != destinationBus) {
102         // in-place processing was not possible - so copy
103         destinationBus->copyFrom(*renderedBus);
104     }
105
106     // Process nodes which need a little extra help because they are not connected to anything, but still need to process.
107     context().processAutomaticPullNodes(numberOfFrames);
108
109     // Let the context take care of any business at the end of each render quantum.
110     context().handlePostRenderTasks();
111     
112     // Advance current sample-frame.
113     m_currentSampleFrame += numberOfFrames;
114
115     if (workletGlobalScope)
116         workletGlobalScope->handlePostRenderTasks(m_currentSampleFrame);
117 }
118
119 void AudioDestinationNode::ref()
120 {
121     context().ref();
122 }
123
124 void AudioDestinationNode::deref()
125 {
126     context().deref();
127 }
128
129 } // namespace WebCore
130
131 #endif // ENABLE(WEB_AUDIO)