OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "modules/webaudio/AudioWorkletGlobalScope.h" | 5 #include "modules/webaudio/AudioWorkletGlobalScope.h" |
6 | 6 |
7 #include "bindings/core/v8/IDLTypes.h" | 7 #include "bindings/core/v8/IDLTypes.h" |
8 #include "bindings/core/v8/NativeValueTraitsImpl.h" | 8 #include "bindings/core/v8/NativeValueTraitsImpl.h" |
9 #include "bindings/core/v8/ToV8ForCore.h" | 9 #include "bindings/core/v8/ToV8ForCore.h" |
10 #include "bindings/core/v8/V8BindingForCore.h" | 10 #include "bindings/core/v8/V8BindingForCore.h" |
| 11 #include "bindings/core/v8/V8ObjectBuilder.h" |
11 #include "bindings/core/v8/WorkerOrWorkletScriptController.h" | 12 #include "bindings/core/v8/WorkerOrWorkletScriptController.h" |
12 #include "bindings/modules/v8/V8AudioParamDescriptor.h" | 13 #include "bindings/modules/v8/V8AudioParamDescriptor.h" |
| 14 #include "core/dom/DOMTypedArray.h" |
13 #include "core/dom/ExceptionCode.h" | 15 #include "core/dom/ExceptionCode.h" |
14 #include "modules/webaudio/AudioBuffer.h" | 16 #include "modules/webaudio/AudioBuffer.h" |
15 #include "modules/webaudio/AudioParamDescriptor.h" | 17 #include "modules/webaudio/AudioParamDescriptor.h" |
16 #include "modules/webaudio/AudioWorkletProcessor.h" | 18 #include "modules/webaudio/AudioWorkletProcessor.h" |
17 #include "modules/webaudio/AudioWorkletProcessorDefinition.h" | 19 #include "modules/webaudio/AudioWorkletProcessorDefinition.h" |
| 20 #include "platform/audio/AudioUtilities.h" |
18 #include "platform/bindings/V8BindingMacros.h" | 21 #include "platform/bindings/V8BindingMacros.h" |
19 #include "platform/bindings/V8ObjectConstructor.h" | 22 #include "platform/bindings/V8ObjectConstructor.h" |
20 #include "platform/weborigin/SecurityOrigin.h" | 23 #include "platform/weborigin/SecurityOrigin.h" |
21 | 24 |
22 namespace blink { | 25 namespace blink { |
23 | 26 |
24 AudioWorkletGlobalScope* AudioWorkletGlobalScope::Create( | 27 AudioWorkletGlobalScope* AudioWorkletGlobalScope::Create( |
25 const KURL& url, | 28 const KURL& url, |
26 const String& user_agent, | 29 const String& user_agent, |
27 PassRefPtr<SecurityOrigin> security_origin, | 30 PassRefPtr<SecurityOrigin> security_origin, |
28 v8::Isolate* isolate, | 31 v8::Isolate* isolate, |
29 WorkerThread* thread, | 32 WorkerThread* thread, |
30 WorkerClients* worker_clients) { | 33 WorkerClients* worker_clients) { |
| 34 LOG(INFO) << "AudioWorkletGlobalScope::RegisterProcessor thread = " |
| 35 << thread; |
31 return new AudioWorkletGlobalScope(url, user_agent, | 36 return new AudioWorkletGlobalScope(url, user_agent, |
32 std::move(security_origin), isolate, | 37 std::move(security_origin), isolate, |
33 thread, worker_clients); | 38 thread, worker_clients); |
34 } | 39 } |
35 | 40 |
36 AudioWorkletGlobalScope::AudioWorkletGlobalScope( | 41 AudioWorkletGlobalScope::AudioWorkletGlobalScope( |
37 const KURL& url, | 42 const KURL& url, |
38 const String& user_agent, | 43 const String& user_agent, |
39 PassRefPtr<SecurityOrigin> security_origin, | 44 PassRefPtr<SecurityOrigin> security_origin, |
40 v8::Isolate* isolate, | 45 v8::Isolate* isolate, |
(...skipping 24 matching lines...) Expand all Loading... |
65 // TODO(hongchan): this is not stated in the spec, but seems necessary. | 70 // TODO(hongchan): this is not stated in the spec, but seems necessary. |
66 // https://github.com/WebAudio/web-audio-api/issues/1172 | 71 // https://github.com/WebAudio/web-audio-api/issues/1172 |
67 if (name.IsEmpty()) { | 72 if (name.IsEmpty()) { |
68 exception_state.ThrowTypeError("The empty string is not a valid name."); | 73 exception_state.ThrowTypeError("The empty string is not a valid name."); |
69 return; | 74 return; |
70 } | 75 } |
71 | 76 |
72 v8::Isolate* isolate = ScriptController()->GetScriptState()->GetIsolate(); | 77 v8::Isolate* isolate = ScriptController()->GetScriptState()->GetIsolate(); |
73 v8::Local<v8::Context> context = ScriptController()->GetContext(); | 78 v8::Local<v8::Context> context = ScriptController()->GetContext(); |
74 | 79 |
| 80 // Get a handle for the class definition (i.e. constructor) |
75 if (!class_definition.V8Value()->IsFunction()) { | 81 if (!class_definition.V8Value()->IsFunction()) { |
76 exception_state.ThrowTypeError( | 82 exception_state.ThrowTypeError( |
77 "The processor definition is neither 'class' nor 'function'."); | 83 "The processor definition is neither 'class' nor 'function'."); |
78 return; | 84 return; |
79 } | 85 } |
80 | 86 |
81 v8::Local<v8::Function> class_definition_local = | 87 v8::Local<v8::Function> class_definition_local = |
82 v8::Local<v8::Function>::Cast(class_definition.V8Value()); | 88 v8::Local<v8::Function>::Cast(class_definition.V8Value()); |
83 | 89 |
| 90 // Get a handle for |prototype| object out of class definition. |
84 v8::Local<v8::Value> prototype_value_local; | 91 v8::Local<v8::Value> prototype_value_local; |
85 bool prototype_extracted = | 92 bool prototype_extracted = |
86 class_definition_local->Get(context, V8String(isolate, "prototype")) | 93 class_definition_local->Get(context, V8String(isolate, "prototype")) |
87 .ToLocal(&prototype_value_local); | 94 .ToLocal(&prototype_value_local); |
88 DCHECK(prototype_extracted); | 95 DCHECK(prototype_extracted); |
89 | 96 |
90 v8::Local<v8::Object> prototype_object_local = | 97 v8::Local<v8::Object> prototype_object_local = |
91 v8::Local<v8::Object>::Cast(prototype_value_local); | 98 v8::Local<v8::Object>::Cast(prototype_value_local); |
92 | 99 |
| 100 // Extract |process| function. |
93 v8::Local<v8::Value> process_value_local; | 101 v8::Local<v8::Value> process_value_local; |
94 bool process_extracted = | 102 bool process_extracted = |
95 prototype_object_local->Get(context, V8String(isolate, "process")) | 103 prototype_object_local->Get(context, V8String(isolate, "process")) |
96 .ToLocal(&process_value_local); | 104 .ToLocal(&process_value_local); |
97 DCHECK(process_extracted); | 105 DCHECK(process_extracted); |
98 | 106 |
99 if (process_value_local->IsNullOrUndefined()) { | 107 if (process_value_local->IsNullOrUndefined()) { |
100 exception_state.ThrowTypeError( | 108 exception_state.ThrowTypeError( |
101 "The 'process' function does not exist in the prototype."); | 109 "The 'process' function does not exist in the prototype."); |
102 return; | 110 return; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 AudioWorkletProcessorDefinition* definition = FindDefinition(name); | 159 AudioWorkletProcessorDefinition* definition = FindDefinition(name); |
152 if (!definition) | 160 if (!definition) |
153 return nullptr; | 161 return nullptr; |
154 | 162 |
155 // V8 object instance construction: this construction process is here to make | 163 // V8 object instance construction: this construction process is here to make |
156 // the AudioWorkletProcessor class a thin wrapper of V8::Object instance. | 164 // the AudioWorkletProcessor class a thin wrapper of V8::Object instance. |
157 v8::Isolate* isolate = ScriptController()->GetScriptState()->GetIsolate(); | 165 v8::Isolate* isolate = ScriptController()->GetScriptState()->GetIsolate(); |
158 v8::Local<v8::Object> instance_local; | 166 v8::Local<v8::Object> instance_local; |
159 if (!V8ObjectConstructor::NewInstance(isolate, | 167 if (!V8ObjectConstructor::NewInstance(isolate, |
160 definition->ConstructorLocal(isolate)) | 168 definition->ConstructorLocal(isolate)) |
161 .ToLocal(&instance_local)) { | 169 .ToLocal(&instance_local)) { |
162 return nullptr; | 170 return nullptr; |
163 } | 171 } |
164 | 172 |
165 AudioWorkletProcessor* processor = AudioWorkletProcessor::Create(this, name); | 173 AudioWorkletProcessor* processor = |
| 174 AudioWorkletProcessor::Create(this, definition); |
166 DCHECK(processor); | 175 DCHECK(processor); |
167 | 176 |
168 processor->SetInstance(isolate, instance_local); | 177 processor->SetInstance(isolate, instance_local); |
169 processor_instances_.push_back( | 178 processor_instances_.push_back( |
170 TraceWrapperMember<AudioWorkletProcessor>(this, processor)); | 179 TraceWrapperMember<AudioWorkletProcessor>(this, processor)); |
171 | 180 |
172 return processor; | 181 return processor; |
173 } | 182 } |
174 | 183 |
175 bool AudioWorkletGlobalScope::Process(AudioWorkletProcessor* processor, | 184 bool AudioWorkletGlobalScope::Process( |
176 AudioBuffer* input_buffer, | 185 AudioWorkletProcessor* processor, |
177 AudioBuffer* output_buffer) { | 186 AudioBuffer* input_buffer, |
| 187 AudioBuffer* output_buffer, |
| 188 HashMap<String, AudioFloatArray*> audio_param_data_map) { |
178 CHECK(input_buffer); | 189 CHECK(input_buffer); |
179 CHECK(output_buffer); | 190 CHECK(output_buffer); |
180 | 191 |
181 ScriptState* script_state = ScriptController()->GetScriptState(); | 192 ScriptState* script_state = ScriptController()->GetScriptState(); |
| 193 v8::Isolate* isolate = script_state->GetIsolate(); |
| 194 |
182 ScriptState::Scope scope(script_state); | 195 ScriptState::Scope scope(script_state); |
183 | 196 |
184 v8::Isolate* isolate = script_state->GetIsolate(); | |
185 AudioWorkletProcessorDefinition* definition = | 197 AudioWorkletProcessorDefinition* definition = |
186 FindDefinition(processor->GetName()); | 198 FindDefinition(processor->GetName()); |
187 DCHECK(definition); | 199 DCHECK(definition); |
188 | 200 |
| 201 V8ObjectBuilder parameters_object(script_state); |
| 202 |
| 203 for (const auto& param_name : audio_param_data_map.Keys()) { |
| 204 DOMFloat32Array* param_data_array = |
| 205 DOMFloat32Array::CreateOrNull(AudioUtilities::kRenderQuantumFrames); |
| 206 const float* source = audio_param_data_map.at(param_name)->Data(); |
| 207 float* destination = param_data_array->Data(); |
| 208 |
| 209 memcpy(destination, source, |
| 210 AudioUtilities::kRenderQuantumFrames * sizeof(float)); |
| 211 |
| 212 parameters_object.Add( |
| 213 StringView(param_name), |
| 214 ToV8(param_data_array, script_state->GetContext()->Global(), isolate)); |
| 215 } |
| 216 |
189 v8::Local<v8::Value> argv[] = { | 217 v8::Local<v8::Value> argv[] = { |
190 ToV8(input_buffer, script_state->GetContext()->Global(), isolate), | 218 ToV8(input_buffer, script_state->GetContext()->Global(), isolate), |
191 ToV8(output_buffer, script_state->GetContext()->Global(), isolate)}; | 219 ToV8(output_buffer, script_state->GetContext()->Global(), isolate), |
| 220 parameters_object.V8Value()}; |
192 | 221 |
193 // TODO(hongchan): Catch exceptions thrown in the process method. The verbose | 222 // TODO(hongchan): Catch exceptions thrown in the process method. The verbose |
194 // options forces the TryCatch object to save the exception location. The | 223 // options forces the TryCatch object to save the exception location. The |
195 // pending exception should be handled later. | 224 // pending exception should be handled later. |
196 v8::TryCatch block(isolate); | 225 v8::TryCatch block(isolate); |
197 block.SetVerbose(true); | 226 block.SetVerbose(true); |
198 | 227 |
199 // Perform JS function process() in AudioWorkletProcessor instance. The actual | 228 // Perform JS function process() in AudioWorkletProcessor instance. The actual |
200 // V8 operation happens here to make the AudioWorkletProcessor class a thin | 229 // V8 operation happens here to make the AudioWorkletProcessor class a thin |
201 // wrapper of v8::Object instance. | 230 // wrapper of v8::Object instance. |
(...skipping 19 matching lines...) Expand all Loading... |
221 for (auto definition : processor_definition_map_) | 250 for (auto definition : processor_definition_map_) |
222 visitor->TraceWrappers(definition.value); | 251 visitor->TraceWrappers(definition.value); |
223 | 252 |
224 for (auto processor : processor_instances_) | 253 for (auto processor : processor_instances_) |
225 visitor->TraceWrappers(processor); | 254 visitor->TraceWrappers(processor); |
226 | 255 |
227 ThreadedWorkletGlobalScope::TraceWrappers(visitor); | 256 ThreadedWorkletGlobalScope::TraceWrappers(visitor); |
228 } | 257 } |
229 | 258 |
230 } // namespace blink | 259 } // namespace blink |
OLD | NEW |