Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1450)

Side by Side Diff: third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.cpp

Issue 2793593002: AudioWorklet prototype
Patch Set: Merge changes, AudioParam bug fix Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "modules/webaudio/AudioWorkletNode.h"
6
7 #include "core/dom/TaskRunnerHelper.h"
8 #include "modules/webaudio/AudioBuffer.h"
9 #include "modules/webaudio/AudioNodeInput.h"
10 #include "modules/webaudio/AudioNodeOutput.h"
11 #include "modules/webaudio/AudioParamDescriptor.h"
12 #include "modules/webaudio/AudioWorkletGlobalScope.h"
13 #include "modules/webaudio/AudioWorkletProcessor.h"
14 #include "modules/webaudio/AudioWorkletProcessorDefinition.h"
15 #include "platform/audio/AudioBus.h"
16 #include "platform/audio/AudioUtilities.h"
17 #include "platform/heap/Persistent.h"
18
19 namespace blink {
20
21 AudioWorkletHandler::AudioWorkletHandler(AudioNode& node,
22 float sample_rate,
23 String name)
24 : AudioHandler(kNodeTypeAudioWorklet, node, sample_rate) {
25 DCHECK(IsMainThread());
26
27 AddInput();
28 AddOutput(1);
29
30 // Post a task for the instantiation of corresponding AudioWorkletProcessor.
31 // This blocks the main thread until the construction is completed.
32 WaitableEvent doneConstruction;
33 Context()->GetWorkletMessagingProxy()->CreateProcessorInstance(
34 name, this, &doneConstruction);
35 doneConstruction.Wait();
36
37 DCHECK(processor_);
38 if (processor_) {
39 const AudioWorkletProcessorDefinition* definition =
40 processor_->GetDefinition();
41 DCHECK(definition);
42
43 HeapHashMap<String, Member<AudioParam>> audio_param_map;
44 for (const auto& descriptor : definition->GetAudioParamDescriptors()) {
45 // A thread-specific isolated copy is necessary since |descriptor| belongs
46 // to the rendering thread and AudioParams are owned by the main thread.
47 String param_name = descriptor.name().IsolatedCopy();
48 AudioParam* audio_param = AudioParam::Create(*Context(),
49 kParamTypeAudioWorklet,
50 descriptor.defaultValue(),
51 descriptor.minValue(),
52 descriptor.maxValue());
53 DCHECK(audio_param);
54 audio_param_map.Set(param_name, audio_param);
55
56 // We need another isolated copy of string because AudioParamHandler is
57 // touched by the rendering thread.
58 param_handler_map_.Set(param_name.IsolatedCopy(),
59 audio_param->HandlerExperimental());
60 }
61
62 static_cast<AudioWorkletNode&>(node).SetParameterMap(
63 new AudioParamMap(audio_param_map));
64
65 // Initialize the handler only when the processor is valid. After this call,
66 // the handler/processor will get pulled by the rendering thread.
67 Initialize();
68 }
69 }
70
71 AudioWorkletHandler::~AudioWorkletHandler() {
72 processor_->Dispose();
73 Uninitialize();
74 processor_ = nullptr;
75 }
76
77 PassRefPtr<AudioWorkletHandler> AudioWorkletHandler::Create(AudioNode& node,
78 float sample_rate,
79 String name) {
80 return AdoptRef(new AudioWorkletHandler(node, sample_rate, name));
81 }
82
83 void AudioWorkletHandler::Process(size_t frames_to_process) {
84 AudioBus* output_bus = Output(0).Bus();
85 DCHECK(output_bus);
86
87 if (!IsInitialized()) {
88 output_bus->Zero();
89 return;
90 }
91
92 AudioBuffer* input_buffer = Input(0).IsConnected()
93 ? AudioBuffer::CreateFromAudioBus(Input(0).Bus())
94 : AudioBuffer::Create(1, 128, Context()->sampleRate());
95 AudioBuffer* output_buffer =
96 AudioBuffer::Create(1, 128, Context()->sampleRate());
97
98 HashMap<String, AudioFloatArray*> audio_param_data_map;
99 for (const auto& param_name : param_handler_map_.Keys()) {
100 AudioParamHandler* audio_param_handler = param_handler_map_.at(param_name);
101 AudioFloatArray* param_values =
102 new AudioFloatArray(AudioUtilities::kRenderQuantumFrames);
103 if (audio_param_handler->HasSampleAccurateValues()) {
104 audio_param_handler->CalculateSampleAccurateValues(
105 param_values->Data(), frames_to_process);
106 } else {
107 std::fill(param_values->Data(),
108 param_values->Data() + AudioUtilities::kRenderQuantumFrames,
109 audio_param_handler->Value());
110 }
111
112 audio_param_data_map.Set(param_name, param_values);
113 }
114
115 processor_->Process(input_buffer, output_buffer, audio_param_data_map);
116
117 for (unsigned i = 0; i < 1; ++i) {
118 memcpy(output_bus->Channel(i)->MutableData(),
119 output_buffer->getChannelData(i).View()->Data(),
120 sizeof(float) * frames_to_process);
121 }
122 }
123
124 double AudioWorkletHandler::TailTime() const {
125 return std::numeric_limits<double>::infinity();
126 }
127
128 double AudioWorkletHandler::LatencyTime() const {
129 return std::numeric_limits<double>::infinity();
130 }
131
132 void AudioWorkletHandler::SetProcessorOnRenderingThread(
133 AudioWorkletProcessor* processor) {
134 DCHECK(!IsMainThread());
135 processor_ = processor;
136 }
137
138 // ----------------------------------------------------------------
139
140 AudioWorkletNode::AudioWorkletNode(BaseAudioContext& context,
141 const String& name)
142 : AudioNode(context), name_(name) {
143 SetHandler(AudioWorkletHandler::Create(*this, context.sampleRate(), name));
144
145 DCHECK(parameter_map_);
146 }
147
148 AudioWorkletNode* AudioWorkletNode::Create(BaseAudioContext* context,
149 const String& name,
150 ExceptionState& exception_state) {
151 DCHECK(IsMainThread());
152
153 if (context->IsContextClosed()) {
154 context->ThrowExceptionForClosedState(exception_state);
155 return nullptr;
156 }
157
158 // Create instance of node; this will set the instance of handler as well.
159 // Once the handler is ready then create AudioParam objects in AudioParamMap.
160 AudioWorkletNode* node = new AudioWorkletNode(*context, name);
161
162 if (!node || !node->GetWorkletHandler().IsInitialized())
163 return nullptr;
164
165 // Do something with node.
166 // node->handleChannelOptions(options, exception_state);
167
168 // context keeps reference as a source node.
169 context->NotifySourceNodeStartedProcessing(node);
170
171 return node;
172 }
173
174 bool AudioWorkletNode::HasPendingActivity() const {
175 return !context()->IsContextClosed();
176 }
177
178 AudioParamMap* AudioWorkletNode::parameters() const {
179 return parameter_map_;
180 }
181
182 void AudioWorkletNode::SetParameterMap(AudioParamMap* parameter_map) {
183 parameter_map_ = parameter_map;
184 }
185
186 AudioWorkletHandler& AudioWorkletNode::GetWorkletHandler() const {
187 return static_cast<AudioWorkletHandler&>(Handler());
188 }
189
190 DEFINE_TRACE(AudioWorkletNode) {
191 visitor->Trace(parameter_map_);
192 AudioNode::Trace(visitor);
193 }
194
195 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698