diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp index 2f614997b44..c863dfce056 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp @@ -34,6 +34,7 @@ static bool is_platform_object(Type const& type) "AnimationEffect"sv, "AnimationTimeline"sv, "Attr"sv, + "AudioBuffer"sv, "AudioNode"sv, "AudioParam"sv, "AudioScheduledSourceNode"sv, @@ -2523,7 +2524,7 @@ JS::ThrowCompletionOr> @constructor_class@::constru auto prototype = TRY(new_target.get(vm.names.prototype)); // 3.3. If Type(prototype) is not Object, then: - if (!prototype.is_object()) { + if (!prototype.is_object()) { // 1. Let targetRealm be ? GetFunctionRealm(newTarget). auto* target_realm = TRY(JS::get_function_realm(vm, new_target)); diff --git a/Meta/gn/secondary/Userland/Libraries/LibWeb/WebAudio/BUILD.gn b/Meta/gn/secondary/Userland/Libraries/LibWeb/WebAudio/BUILD.gn index c0bfe928252..d5fbc36d492 100644 --- a/Meta/gn/secondary/Userland/Libraries/LibWeb/WebAudio/BUILD.gn +++ b/Meta/gn/secondary/Userland/Libraries/LibWeb/WebAudio/BUILD.gn @@ -6,6 +6,8 @@ source_set("WebAudio") { sources = [ "AudioBuffer.cpp", "AudioBuffer.h", + "AudioBufferSourceNode.cpp", + "AudioBufferSourceNode.h", "AudioContext.cpp", "AudioContext.h", "AudioNode.cpp", diff --git a/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni b/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni index d0ef89d2c16..9e6e5dfc31a 100644 --- a/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni +++ b/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni @@ -319,6 +319,7 @@ standard_idl_files = [ "//Userland/Libraries/LibWeb/WebAssembly/Module.idl", "//Userland/Libraries/LibWeb/WebAssembly/Table.idl", "//Userland/Libraries/LibWeb/WebAudio/AudioBuffer.idl", + "//Userland/Libraries/LibWeb/WebAudio/AudioBufferSourceNode.idl", "//Userland/Libraries/LibWeb/WebAudio/AudioContext.idl", "//Userland/Libraries/LibWeb/WebAudio/AudioNode.idl", "//Userland/Libraries/LibWeb/WebAudio/AudioParam.idl", diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index f09962c021a..0878d5d36ca 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -682,6 +682,7 @@ set(SOURCES WebAssembly/Table.cpp WebAssembly/WebAssembly.cpp WebAudio/AudioBuffer.cpp + WebAudio/AudioBufferSourceNode.cpp WebAudio/AudioContext.cpp WebAudio/AudioNode.cpp WebAudio/AudioParam.cpp diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 6e94546205d..720cbb2fcdf 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -711,6 +711,7 @@ class Table; namespace Web::WebAudio { class AudioBuffer; +class AudioBufferSourceNode; class AudioContext; class AudioNode; class AudioParam; diff --git a/Userland/Libraries/LibWeb/WebAudio/AudioBufferSourceNode.cpp b/Userland/Libraries/LibWeb/WebAudio/AudioBufferSourceNode.cpp new file mode 100644 index 00000000000..4304b2b701c --- /dev/null +++ b/Userland/Libraries/LibWeb/WebAudio/AudioBufferSourceNode.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2024, Bar Yemini + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include + +namespace Web::WebAudio { + +JS_DEFINE_ALLOCATOR(AudioBufferSourceNode); + +AudioBufferSourceNode::AudioBufferSourceNode(JS::Realm& realm, JS::NonnullGCPtr context, AudioBufferSourceOptions const&) + : AudioScheduledSourceNode(realm, context) +{ +} + +AudioBufferSourceNode::~AudioBufferSourceNode() = default; + +WebIDL::ExceptionOr> AudioBufferSourceNode::create(JS::Realm& realm, JS::NonnullGCPtr context, AudioBufferSourceOptions const& options) +{ + return construct_impl(realm, context, options); +} + +// https://webaudio.github.io/web-audio-api/#dom-audiobuffersourcenode-audiobuffersourcenode +WebIDL::ExceptionOr> AudioBufferSourceNode::construct_impl(JS::Realm& realm, JS::NonnullGCPtr context, AudioBufferSourceOptions const& options) +{ + // When the constructor is called with a BaseAudioContext c and an option object option, the user agent + // MUST initialize the AudioNode this, with context and options as arguments. + + auto node = realm.vm().heap().allocate(realm, realm, context, options); + return node; +} + +void AudioBufferSourceNode::initialize(JS::Realm& realm) +{ + Base::initialize(realm); + WEB_SET_PROTOTYPE_FOR_INTERFACE(AudioBufferSourceNode); +} + +void AudioBufferSourceNode::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); +} + +} diff --git a/Userland/Libraries/LibWeb/WebAudio/AudioBufferSourceNode.h b/Userland/Libraries/LibWeb/WebAudio/AudioBufferSourceNode.h new file mode 100644 index 00000000000..e87070f67b8 --- /dev/null +++ b/Userland/Libraries/LibWeb/WebAudio/AudioBufferSourceNode.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024, Bar Yemini + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Web::WebAudio { + +// https://webaudio.github.io/web-audio-api/#AudioBufferSourceOptions +struct AudioBufferSourceOptions { + JS::GCPtr buffer; + float detune { 0 }; + bool loop { false }; + double loop_end { 0 }; + double loop_start { 0 }; + float playback_rate { 1 }; +}; + +// https://webaudio.github.io/web-audio-api/#AudioBufferSourceNode +class AudioBufferSourceNode : public AudioScheduledSourceNode { + WEB_PLATFORM_OBJECT(AudioBufferSourceNode, AudioScheduledSourceNode); + JS_DECLARE_ALLOCATOR(AudioBufferSourceNode); + +public: + virtual ~AudioBufferSourceNode() override; + + static WebIDL::ExceptionOr> create(JS::Realm&, JS::NonnullGCPtr, AudioBufferSourceOptions const& = {}); + static WebIDL::ExceptionOr> construct_impl(JS::Realm&, JS::NonnullGCPtr, AudioBufferSourceOptions const& = {}); + +protected: + AudioBufferSourceNode(JS::Realm&, JS::NonnullGCPtr, AudioBufferSourceOptions const& = {}); + + virtual void initialize(JS::Realm&) override; + virtual void visit_edges(Cell::Visitor&) override; +}; + +} diff --git a/Userland/Libraries/LibWeb/WebAudio/AudioBufferSourceNode.idl b/Userland/Libraries/LibWeb/WebAudio/AudioBufferSourceNode.idl new file mode 100644 index 00000000000..0ee9b113510 --- /dev/null +++ b/Userland/Libraries/LibWeb/WebAudio/AudioBufferSourceNode.idl @@ -0,0 +1,26 @@ +#import +#import +#import +#import + +dictionary AudioBufferSourceOptions { + AudioBuffer? buffer; + float detune = 0; + boolean loop = false; + double loopEnd = 0; + double loopStart = 0; + float playbackRate = 1; +}; + +// https://webaudio.github.io/web-audio-api/#AudioBufferSourceNode +[Exposed=Window] +interface AudioBufferSourceNode : AudioScheduledSourceNode { + constructor(BaseAudioContext context, optional AudioBufferSourceOptions options = {}); + [FIXME] attribute AudioBuffer? buffer; + [FIXME] readonly attribute AudioParam playbackRate; + [FIXME] readonly attribute AudioParam detune; + [FIXME] attribute boolean loop; + [FIXME] attribute double loopStart; + [FIXME] attribute double loopEnd; + [FIXME] undefined start(optional double when = 0, optional double offset, optional double duration); +}; diff --git a/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.cpp b/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.cpp index 6bd67d0fa23..c6eef658501 100644 --- a/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.cpp +++ b/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,13 @@ WebIDL::ExceptionOr> BaseAudioContext::create_buff return AudioBuffer::create(realm(), number_of_channels, length, sample_rate); } +// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-createbuffersource +WebIDL::ExceptionOr> BaseAudioContext::create_buffer_source() +{ + // Factory method for a AudioBufferSourceNode. + return AudioBufferSourceNode::create(realm(), *this); +} + // https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-createoscillator WebIDL::ExceptionOr> BaseAudioContext::create_oscillator() { diff --git a/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.h b/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.h index 687deec85fb..2bd927991d5 100644 --- a/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.h +++ b/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.h @@ -48,6 +48,7 @@ public: static WebIDL::ExceptionOr verify_audio_options_inside_nominal_range(JS::Realm&, WebIDL::UnsignedLong number_of_channels, WebIDL::UnsignedLong length, float sample_rate); WebIDL::ExceptionOr> create_buffer(WebIDL::UnsignedLong number_of_channels, WebIDL::UnsignedLong length, float sample_rate); + WebIDL::ExceptionOr> create_buffer_source(); WebIDL::ExceptionOr> create_oscillator(); WebIDL::ExceptionOr> create_dynamics_compressor(); JS::NonnullGCPtr create_gain(); diff --git a/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.idl b/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.idl index 5a2132d68b8..6a358c54eb4 100644 --- a/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.idl +++ b/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.idl @@ -1,6 +1,7 @@ #import #import #import +#import #import #import #import @@ -27,7 +28,7 @@ interface BaseAudioContext : EventTarget { [FIXME] AnalyserNode createAnalyser (); [FIXME] BiquadFilterNode createBiquadFilter (); AudioBuffer createBuffer(unsigned long numberOfChannels, unsigned long length, float sampleRate); - [FIXME] AudioBufferSourceNode createBufferSource (); + AudioBufferSourceNode createBufferSource (); [FIXME] ChannelMergerNode createChannelMerger (optional unsigned long numberOfInputs = 6); [FIXME] ChannelSplitterNode createChannelSplitter (optional unsigned long numberOfOutputs = 6); [FIXME] ConstantSourceNode createConstantSource (); diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index 671191d2f68..0fcfbece629 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -310,6 +310,7 @@ libweb_js_bindings(WebAssembly/Module) libweb_js_bindings(WebAssembly/Table) libweb_js_bindings(WebAssembly/WebAssembly NAMESPACE) libweb_js_bindings(WebAudio/AudioBuffer) +libweb_js_bindings(WebAudio/AudioBufferSourceNode) libweb_js_bindings(WebAudio/AudioContext) libweb_js_bindings(WebAudio/AudioNode) libweb_js_bindings(WebAudio/AudioParam)