LibWeb/WebAudio: Add stable IDs to AudioNodes
Modeled after UniqueNodeID and uses incremental counter on BaseAudioContext to assign IDs.
This commit is contained in:
parent
0796418c18
commit
d942b98549
7 changed files with 44 additions and 20 deletions
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Shannon Booth <shannon@serenityos.org>
|
||||
* Copyright (c) 2025, Ben Eidson <b.e.eidson@gmail.com>
|
||||
* Copyright (c) 2025-2026, Ben Eidson <b.e.eidson@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
|
@ -17,6 +17,7 @@ AudioNode::AudioNode(JS::Realm& realm, GC::Ref<BaseAudioContext> context, WebIDL
|
|||
: DOM::EventTarget(realm)
|
||||
, m_context(context)
|
||||
, m_channel_count(channel_count)
|
||||
, m_node_id(context->next_node_id({}))
|
||||
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Shannon Booth <shannon@serenityos.org>
|
||||
* Copyright (c) 2025, Ben Eidson <b.e.eidson@gmail.com>
|
||||
* Copyright (c) 2025-2026, Ben Eidson <b.e.eidson@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
|
@ -12,6 +12,7 @@
|
|||
#include <LibWeb/Bindings/AudioNodePrototype.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
#include <LibWeb/DOM/EventTarget.h>
|
||||
#include <LibWeb/WebAudio/Types.h>
|
||||
#include <LibWeb/WebIDL/Types.h>
|
||||
|
||||
namespace Web::WebAudio {
|
||||
|
|
@ -86,6 +87,8 @@ public:
|
|||
|
||||
WebIDL::ExceptionOr<void> initialize_audio_node_options(AudioNodeOptions const& given_options, AudioNodeDefaultOptions const& default_options);
|
||||
|
||||
NodeID node_id() const { return m_node_id; }
|
||||
|
||||
protected:
|
||||
AudioNode(JS::Realm&, GC::Ref<BaseAudioContext>, WebIDL::UnsignedLong channel_count = 2);
|
||||
|
||||
|
|
@ -103,6 +106,7 @@ private:
|
|||
Vector<AudioNodeConnection> m_output_connections;
|
||||
// Connections from this node's outputs into AudioParams.
|
||||
Vector<AudioParamConnection> m_param_connections;
|
||||
NodeID const m_node_id;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,9 +51,7 @@ WebIDL::ExceptionOr<void> AudioScheduledSourceNode::start(double when)
|
|||
set_source_started(true);
|
||||
|
||||
// 4. Queue a control message to start the AudioScheduledSourceNode, including the parameter values in the message.
|
||||
// FIXME: Include a stable source id so the rendering thread can route this message to the correct AudioScheduledSourceNode
|
||||
// once render-thread scheduling is implemented.
|
||||
context()->queue_control_message(StartSource { .when = when });
|
||||
context()->queue_control_message(StartSource { .node_id = node_id(), .when = when });
|
||||
|
||||
// FIXME: 5. Send a control message to the associated AudioContext to start running its rendering thread only when all the following conditions are met:
|
||||
|
||||
|
|
@ -73,9 +71,7 @@ WebIDL::ExceptionOr<void> AudioScheduledSourceNode::stop(double when)
|
|||
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::RangeError, "when must not be negative"sv };
|
||||
|
||||
// 3. Queue a control message to stop the AudioScheduledSourceNode, including the parameter values in the message.
|
||||
// FIXME: Include a stable source id so the rendering thread can route this message to the correct AudioScheduledSourceNode
|
||||
// once render-thread scheduling is implemented.
|
||||
context()->queue_control_message(StopSource { .when = when });
|
||||
context()->queue_control_message(StopSource { .node_id = node_id(), .when = when });
|
||||
|
||||
return {};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include <LibWeb/WebAudio/PeriodicWave.h>
|
||||
#include <LibWeb/WebAudio/ScriptProcessorNode.h>
|
||||
#include <LibWeb/WebAudio/StereoPannerNode.h>
|
||||
#include <LibWeb/WebAudio/Types.h>
|
||||
#include <LibWeb/WebIDL/Types.h>
|
||||
|
||||
namespace Web::WebAudio {
|
||||
|
|
@ -89,6 +90,8 @@ public:
|
|||
|
||||
void queue_control_message(ControlMessage);
|
||||
|
||||
NodeID next_node_id(Badge<AudioNode>) { return ++m_next_node_id; }
|
||||
|
||||
protected:
|
||||
explicit BaseAudioContext(JS::Realm&, float m_sample_rate = 0);
|
||||
|
||||
|
|
@ -106,6 +109,8 @@ private:
|
|||
|
||||
void queue_a_decoding_operation(GC::Ref<JS::PromiseCapability>, GC::Root<WebIDL::BufferSource>, GC::Ptr<WebIDL::CallbackType>, GC::Ptr<WebIDL::CallbackType>);
|
||||
|
||||
u64 m_next_node_id { 0 };
|
||||
|
||||
float m_sample_rate { 0 };
|
||||
double m_current_time { 0 };
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2025, Ben Eidson <b.e.eidson@gmail.com>
|
||||
* Copyright (c) 2025-2026, Ben Eidson <b.e.eidson@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
|
@ -7,22 +7,21 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/Variant.h>
|
||||
#include <LibWeb/WebAudio/Types.h>
|
||||
|
||||
namespace Web::WebAudio {
|
||||
|
||||
using SourceId = u64;
|
||||
|
||||
struct StartSource {
|
||||
SourceId id { 0 }; // FIXME: stable per-source id for render-thread routing
|
||||
NodeID node_id { 0 };
|
||||
double when { 0.0 };
|
||||
};
|
||||
|
||||
struct StopSource {
|
||||
SourceId id { 0 }; // FIXME: stable per-source id for render-thread routing
|
||||
NodeID node_id { 0 };
|
||||
double when { 0.0 };
|
||||
};
|
||||
|
||||
// FIXME: add more event types
|
||||
// FIXME: add more message types
|
||||
|
||||
// https://webaudio.github.io/web-audio-api/#control-message
|
||||
using ControlMessage = Variant<StartSource, StopSource>;
|
||||
|
|
|
|||
16
Libraries/LibWeb/WebAudio/Types.h
Normal file
16
Libraries/LibWeb/WebAudio/Types.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2026, Ben Eidson <b.e.eidson@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/DistinctNumeric.h>
|
||||
|
||||
namespace Web::WebAudio {
|
||||
|
||||
// Stable identifier for AudioNode instances within a BaseAudioContext.
|
||||
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, NodeID, CastToUnderlying);
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2025, Ben Eidson <b.e.eidson@gmail.com>
|
||||
* Copyright (c) 2025-2026, Ben Eidson <b.e.eidson@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
|
@ -12,8 +12,8 @@ TEST_CASE(drain_returns_all_and_clears)
|
|||
{
|
||||
Web::WebAudio::ControlMessageQueue queue;
|
||||
|
||||
queue.enqueue(Web::WebAudio::StartSource { .when = 1.0 });
|
||||
queue.enqueue(Web::WebAudio::StopSource { .when = 2.0 });
|
||||
queue.enqueue(Web::WebAudio::StartSource { .node_id = Web::WebAudio::NodeID { 0 }, .when = 1.0 });
|
||||
queue.enqueue(Web::WebAudio::StopSource { .node_id = Web::WebAudio::NodeID { 1 }, .when = 2.0 });
|
||||
|
||||
auto batch = queue.drain();
|
||||
EXPECT_EQ(batch.size(), 2u);
|
||||
|
|
@ -26,19 +26,22 @@ TEST_CASE(drain_preserves_first_in_first_out)
|
|||
{
|
||||
Web::WebAudio::ControlMessageQueue queue;
|
||||
|
||||
queue.enqueue(Web::WebAudio::StartSource { .when = 1.0 });
|
||||
queue.enqueue(Web::WebAudio::StopSource { .when = 2.0 });
|
||||
queue.enqueue(Web::WebAudio::StartSource { .when = 3.0 });
|
||||
queue.enqueue(Web::WebAudio::StartSource { .node_id = Web::WebAudio::NodeID { 0 }, .when = 1.0 });
|
||||
queue.enqueue(Web::WebAudio::StopSource { .node_id = Web::WebAudio::NodeID { 1 }, .when = 2.0 });
|
||||
queue.enqueue(Web::WebAudio::StartSource { .node_id = Web::WebAudio::NodeID { 2 }, .when = 3.0 });
|
||||
|
||||
auto batch = queue.drain();
|
||||
EXPECT_EQ(batch.size(), 3u);
|
||||
|
||||
EXPECT(batch[0].has<Web::WebAudio::StartSource>());
|
||||
EXPECT_EQ(batch[0].get<Web::WebAudio::StartSource>().when, 1.0);
|
||||
EXPECT_EQ(batch[0].get<Web::WebAudio::StartSource>().node_id, 0u);
|
||||
|
||||
EXPECT(batch[1].has<Web::WebAudio::StopSource>());
|
||||
EXPECT_EQ(batch[1].get<Web::WebAudio::StopSource>().when, 2.0);
|
||||
EXPECT_EQ(batch[1].get<Web::WebAudio::StopSource>().node_id, Web::WebAudio::NodeID { 1 });
|
||||
|
||||
EXPECT(batch[2].has<Web::WebAudio::StartSource>());
|
||||
EXPECT_EQ(batch[2].get<Web::WebAudio::StartSource>().when, 3.0);
|
||||
EXPECT_EQ(batch[2].get<Web::WebAudio::StartSource>().node_id, Web::WebAudio::NodeID { 2 });
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue