Skip to content

Commit

Permalink
Initialize sampleRate in AudioWorkletGlobalScope upon construction
Browse files Browse the repository at this point in the history
This CL changes how |sampleRate| in AudioWorkletGlobalScope is updated.

Previously, the sample rate was updated when the first processor was
created, thus accessing the sample rate in the class definition phase
gives 0 value. With this CL, the sample rate is initialized as soon
as the global scope is created, before the script is loaded/parsed.

Bug: 815313
Test: http/tests/webaudio/audio-worklet/global-sample-rate.html
Change-Id: I994ee70c10ed93618b28c7d29df42b5d458c74f8
Reviewed-on: https://chromium-review.googlesource.com/935747
Commit-Queue: Hongchan Choi <hongchan@chromium.org>
Reviewed-by: Raymond Toy <rtoy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#539254}
  • Loading branch information
hoch authored and Commit Bot committed Feb 26, 2018
1 parent cba0bcc commit 70d15d5
Show file tree
Hide file tree
Showing 11 changed files with 118 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<!DOCTYPE html>
<html>
<head>
<title>
Test sampleRate in AudioWorkletGlobalScope
</title>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="../../../webaudio-resources/audit.js"></script>
<script src="audio-worklet-common.js"></script>
</head>
<body>
<script id="layout-test-code">
// TODO(hongchan): remove this assertion when AudioWorklet shipped.
assertAudioWorklet();

let audit = Audit.createTaskRunner();

let sampleRate = 48000;
let renderLength = 512;
let context = new OfflineAudioContext(1, renderLength, sampleRate);

// Without rendering the context, attempt to access |sampleRate| in the
// global scope as soon as it is created.
audit.define(
'Query |sampleRate| upon AudioWorkletGlobalScope construction',
(task, should) => {
let onePoleFilterNode =
new AudioWorkletNode(context, 'one-pole-filter');
let frequencyParam = onePoleFilterNode.parameters.get('frequency');

should(frequencyParam.maxValue,
'frequencyParam.maxValue')
.beEqualTo(0.5 * context.sampleRate);

task.done();
});

context.audioWorklet.addModule('one-pole-processor.js').then(() => {
audit.run();
});
</script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* @class OnePoleFilter
* @extends AudioWorkletProcessor
*
* A simple One-pole filter.
*/

class OnePoleFilter extends AudioWorkletProcessor {

// This gets evaluated as soon as the global scope is created.
static get parameterDescriptors() {
return [{
name: 'frequency',
defaultValue: 250,
minValue: 0,
maxValue: 0.5 * sampleRate
}];
}

constructor() {
super();
this.updateCoefficientsWithFrequency_(250);
}

updateCoefficientsWithFrequency_(frequency) {
this.b1_ = Math.exp(-2 * Math.PI * frequency / sampleRate);
this.a0_ = 1.0 - this.b1_;
this.z1_ = 0;
}

process(inputs, outputs, parameters) {
let input = inputs[0];
let output = outputs[0];
let frequency = parameters.frequency;
for (let channel = 0; channel < output.length; ++channel) {
let inputChannel = input[channel];
let outputChannel = output[channel];
for (let i = 0; i < outputChannel.length; ++i) {
this.updateCoefficientsWithFrequency_(frequency[i]);
this.z1_ = inputChannel[i] * this.a0_ + this.z1_ * this.b1_;
outputChannel[i] = this.z1_;
}
}

return true;
}
}

registerProcessor('one-pole-filter', OnePoleFilter);
5 changes: 5 additions & 0 deletions third_party/WebKit/Source/modules/webaudio/AudioWorklet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ WebThread* AudioWorklet::GetBackingThread() {
return GetMessagingProxy()->GetWorkletBackingThread();
}

BaseAudioContext* AudioWorklet::GetBaseAudioContext() const {
DCHECK(IsMainThread());
return context_.Get();
}

const Vector<CrossThreadAudioParamInfo>
AudioWorklet::GetParamInfoListForProcessor(
const String& name) {
Expand Down
2 changes: 2 additions & 0 deletions third_party/WebKit/Source/modules/webaudio/AudioWorklet.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ class MODULES_EXPORT AudioWorklet final : public Worklet {

WebThread* GetBackingThread();

BaseAudioContext* GetBaseAudioContext() const;

const Vector<CrossThreadAudioParamInfo> GetParamInfoListForProcessor(
const String& name);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,15 +125,10 @@ void AudioWorkletGlobalScope::registerProcessor(

AudioWorkletProcessor* AudioWorkletGlobalScope::CreateProcessor(
const String& name,
float sample_rate,
MessagePortChannel message_port_channel,
scoped_refptr<SerializedScriptValue> node_options) {
DCHECK(IsContextThread());

// TODO(hongchan): do this only once when the association between
// BaseAudioContext and AudioWorkletGlobalScope is established.
sample_rate_ = sample_rate;

// The registered definition is already checked by AudioWorkletNode
// construction process, so the |definition| here must be valid.
AudioWorkletProcessorDefinition* definition = FindDefinition(name);
Expand Down Expand Up @@ -381,6 +376,10 @@ ProcessorCreationParams* AudioWorkletGlobalScope::GetProcessorCreationParams() {
return processor_creation_params_.get();
}

void AudioWorkletGlobalScope::SetSampleRate(float sample_rate) {
sample_rate_ = sample_rate;
}

void AudioWorkletGlobalScope::Trace(blink::Visitor* visitor) {
visitor->Trace(processor_definition_map_);
visitor->Trace(processor_instances_);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ class MODULES_EXPORT AudioWorkletGlobalScope final
// for some reason.
AudioWorkletProcessor* CreateProcessor(
const String& name,
float sample_rate,
MessagePortChannel,
scoped_refptr<SerializedScriptValue> node_options);

Expand All @@ -96,6 +95,8 @@ class MODULES_EXPORT AudioWorkletGlobalScope final
// is no on-going processor construction, this MUST return nullptr.
ProcessorCreationParams* GetProcessorCreationParams();

void SetSampleRate(float sample_rate);

// IDL
double currentTime() const { return current_time_; }
float sampleRate() const { return sample_rate_; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ namespace {

static const size_t kRenderQuantumFrames = 128;

// This is a typical sample rate.
static const float kTestingSampleRate = 44100;

} // namespace

class AudioWorkletGlobalScopeTest : public PageTestBase {
Expand Down Expand Up @@ -187,7 +184,6 @@ class AudioWorkletGlobalScopeTest : public PageTestBase {

AudioWorkletProcessor* processor =
global_scope->CreateProcessor("testProcessor",
kTestingSampleRate,
dummy_port_channel,
SerializedScriptValue::NullValue());
EXPECT_TRUE(processor);
Expand Down Expand Up @@ -288,7 +284,6 @@ class AudioWorkletGlobalScopeTest : public PageTestBase {
MessagePortChannel dummy_port_channel = channel->port2()->Disentangle();
AudioWorkletProcessor* processor =
global_scope->CreateProcessor("testProcessor",
kTestingSampleRate,
dummy_port_channel,
SerializedScriptValue::NullValue());
EXPECT_TRUE(processor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ void AudioWorkletMessagingProxy::CreateProcessor(
CrossThreadUnretained(GetWorkerThread()),
CrossThreadUnretained(handler),
handler->Name(),
handler->Context()->sampleRate(),
std::move(message_port_channel),
std::move(node_options)));
}
Expand All @@ -44,15 +43,13 @@ void AudioWorkletMessagingProxy::CreateProcessorOnRenderingThread(
WorkerThread* worker_thread,
AudioWorkletHandler* handler,
const String& name,
float sample_rate,
MessagePortChannel message_port_channel,
scoped_refptr<SerializedScriptValue> node_options) {
DCHECK(worker_thread->IsCurrentThread());
AudioWorkletGlobalScope* global_scope =
ToAudioWorkletGlobalScope(worker_thread->GlobalScope());
AudioWorkletProcessor* processor =
global_scope->CreateProcessor(name, sample_rate, message_port_channel,
node_options);
global_scope->CreateProcessor(name, message_port_channel, node_options);
handler->SetProcessorOnRenderThread(processor);
}

Expand Down Expand Up @@ -92,7 +89,8 @@ AudioWorkletMessagingProxy::CreateObjectProxy(
ParentFrameTaskRunners* parent_frame_task_runners) {
return std::make_unique<AudioWorkletObjectProxy>(
static_cast<AudioWorkletMessagingProxy*>(messaging_proxy),
parent_frame_task_runners);
parent_frame_task_runners,
worklet_->GetBaseAudioContext()->sampleRate());
}

std::unique_ptr<WorkerThread> AudioWorkletMessagingProxy::CreateWorkerThread() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ class AudioWorkletMessagingProxy final : public ThreadedWorkletMessagingProxy {
WorkerThread*,
AudioWorkletHandler*,
const String& name,
float sample_rate,
MessagePortChannel,
scoped_refptr<SerializedScriptValue> node_options);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@ namespace blink {

AudioWorkletObjectProxy::AudioWorkletObjectProxy(
AudioWorkletMessagingProxy* messaging_proxy_weak_ptr,
ParentFrameTaskRunners* parent_frame_task_runners)
ParentFrameTaskRunners* parent_frame_task_runners,
float context_sample_rate)
: ThreadedWorkletObjectProxy(
static_cast<ThreadedWorkletMessagingProxy*>(messaging_proxy_weak_ptr),
parent_frame_task_runners) {}
parent_frame_task_runners),
context_sample_rate_(context_sample_rate) {}

void AudioWorkletObjectProxy::DidCreateWorkerGlobalScope(
WorkerOrWorkletGlobalScope* global_scope) {
global_scope_ = ToAudioWorkletGlobalScope(global_scope);
global_scope_->SetSampleRate(context_sample_rate_);
}

void AudioWorkletObjectProxy::DidEvaluateModuleScript(bool success) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ class AudioWorkletObjectProxy final
: public ThreadedWorkletObjectProxy {
public:
AudioWorkletObjectProxy(AudioWorkletMessagingProxy*,
ParentFrameTaskRunners*);
ParentFrameTaskRunners*,
float context_sample_rate);

// Implements WorkerReportingProxy.
void DidCreateWorkerGlobalScope(WorkerOrWorkletGlobalScope*) override;
Expand All @@ -28,6 +29,8 @@ class AudioWorkletObjectProxy final
GetAudioWorkletMessagingProxyWeakPtr();

CrossThreadPersistent<AudioWorkletGlobalScope> global_scope_;

float context_sample_rate_;
};

} // namespace blink
Expand Down

0 comments on commit 70d15d5

Please sign in to comment.