ladybird/Libraries/LibWeb/WebAudio/ScriptProcessorNode.cpp
Jelle Raaijmakers 35ca7f82b0
Some checks are pending
CI / Linux, x86_64, Fuzzers, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer, Clang (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Push notes / build (push) Waiting to run
CI / macOS, arm64, Sanitizer, Clang (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
LibWeb: Add BaseAudioContext::createScriptProcessor()
This is a deprecated node, but it's still widely used on the web.
2025-07-25 11:48:04 +02:00

125 lines
5.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2025, Jelle Raaijmakers <jelle@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "BaseAudioContext.h"
#include <AK/GenericShorthands.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/Bindings/ScriptProcessorNodePrototype.h>
#include <LibWeb/HTML/EventNames.h>
#include <LibWeb/WebAudio/ScriptProcessorNode.h>
namespace Web::WebAudio {
GC_DEFINE_ALLOCATOR(ScriptProcessorNode);
ScriptProcessorNode::ScriptProcessorNode(JS::Realm& realm, GC::Ref<BaseAudioContext> context,
u8 number_of_input_channels, u8 number_of_output_channels)
: AudioNode(realm, context)
, m_number_of_input_channels(number_of_input_channels)
, m_number_of_output_channels(number_of_output_channels)
{
}
ScriptProcessorNode::~ScriptProcessorNode() = default;
WebIDL::ExceptionOr<GC::Ref<ScriptProcessorNode>> ScriptProcessorNode::create(JS::Realm& realm,
GC::Ref<BaseAudioContext> context, WebIDL::Long buffer_size, WebIDL::UnsignedLong number_of_input_channels,
WebIDL::UnsignedLong number_of_output_channels)
{
// https://webaudio.github.io/web-audio-api/#ScriptProcessorNode
// It is invalid for both numberOfInputChannels and numberOfOutputChannels to be zero. In this case an
// IndexSizeError MUST be thrown.
if (number_of_input_channels == 0 && number_of_output_channels == 0) {
return WebIDL::IndexSizeError::create(realm,
"Number of input and output channels cannot both be zero in a ScriptProcessorNode"_string);
}
// This parameter determines the number of channels for this nodes input. The default value is 2. Values of up to
// 32 must be supported. A NotSupportedError must be thrown if the number of channels is not supported.
if (number_of_input_channels > BaseAudioContext::MAX_NUMBER_OF_CHANNELS)
return WebIDL::NotSupportedError::create(realm, "Invalid number of input channels"_string);
// This parameter determines the number of channels for this nodes output. The default value is 2. Values of up to
// 32 must be supported. A NotSupportedError must be thrown if the number of channels is not supported.
if (number_of_output_channels > BaseAudioContext::MAX_NUMBER_OF_CHANNELS)
return WebIDL::NotSupportedError::create(realm, "Invalid number of output channels"_string);
auto script_processor_node = realm.create<ScriptProcessorNode>(realm, context,
number_of_input_channels, number_of_output_channels);
TRY(script_processor_node->set_buffer_size(buffer_size));
// https://webaudio.github.io/web-audio-api/#dom-audionode-channelcountmode
// The channel count mode cannot be changed from "explicit" and an NotSupportedError exception MUST be thrown for
// any attempt to change the value.
TRY(script_processor_node->set_channel_count_mode(Bindings::ChannelCountMode::Explicit));
return script_processor_node;
}
void ScriptProcessorNode::initialize(JS::Realm& realm)
{
WEB_SET_PROTOTYPE_FOR_INTERFACE(ScriptProcessorNode);
Base::initialize(realm);
}
// https://webaudio.github.io/web-audio-api/#ScriptProcessorNode
WebIDL::UnsignedLong ScriptProcessorNode::channel_count() const
{
// This is the number of channels specified when constructing this node.
return m_number_of_input_channels;
}
// https://webaudio.github.io/web-audio-api/#dom-audionode-channelcount
WebIDL::ExceptionOr<void> ScriptProcessorNode::set_channel_count(WebIDL::UnsignedLong)
{
// ScriptProcessorNode: The channel count cannot be changed, and an NotSupportedError exception MUST be thrown for
// any attempt to change the value.
return WebIDL::InvalidStateError::create(realm(),
"Cannot modify channel count in a ScriptProcessorNode"_string);
}
WebIDL::ExceptionOr<void> ScriptProcessorNode::set_channel_count_mode(Bindings::ChannelCountMode channel_count_mode)
{
// https://webaudio.github.io/web-audio-api/#audionode-channelcountmode-constraints
// ScriptProcessorNode: The channel count mode cannot be changed from "explicit" and an NotSupportedError exception
// MUST be thrown for any attempt to change the value.
if (channel_count_mode != Bindings::ChannelCountMode::Explicit)
return WebIDL::InvalidStateError::create(realm(), "Channel count mode must be 'explicit'"_string);
return AudioNode::set_channel_count_mode(channel_count_mode);
}
// https://webaudio.github.io/web-audio-api/#dom-scriptprocessornode-onaudioprocess
GC::Ptr<WebIDL::CallbackType> ScriptProcessorNode::onaudioprocess()
{
return event_handler_attribute(HTML::EventNames::audioprocess);
}
// https://webaudio.github.io/web-audio-api/#dom-scriptprocessornode-onaudioprocess
void ScriptProcessorNode::set_onaudioprocess(GC::Ptr<WebIDL::CallbackType> value)
{
set_event_handler_attribute(HTML::EventNames::audioprocess, value);
}
// https://webaudio.github.io/web-audio-api/#dom-scriptprocessornode-buffersize
WebIDL::ExceptionOr<void> ScriptProcessorNode::set_buffer_size(WebIDL::Long buffer_size)
{
// The size of the buffer (in sample-frames) which needs to be processed each time audioprocess is fired. Legal
// values are (256, 512, 1024, 2048, 4096, 8192, 16384).
// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-createscriptprocessor
// If the value of this parameter is not one of the allowed power-of-2 values listed above, an IndexSizeError MUST
// be thrown.
if (!first_is_one_of(buffer_size, 256, 512, 1024, 2048, 4096, 8192, 16384))
return WebIDL::IndexSizeError::create(realm(), "Unsupported buffer size for a ScriptProcessorNode"_string);
m_buffer_size = buffer_size;
return {};
}
}