From 5cb6d495bb142872c18556cd6cf011163c758aba Mon Sep 17 00:00:00 2001 From: Shannon Booth Date: Thu, 25 Apr 2024 14:45:59 +1200 Subject: [PATCH] LibWeb: Implement verification of 'nominal' audio options The spec doesn't tell us the exact value to use, but a minumum & maximum range of supported values. Just to be consistent with another browser, we follow the values that firefox appears to support from testing the interface on my machine. This function will be used in the AudioBuffer constructor, but is defined in the spec as part of BaseAudioContext. --- .../LibWeb/WebAudio/BaseAudioContext.cpp | 21 +++++++++++++++++++ .../LibWeb/WebAudio/BaseAudioContext.h | 15 +++++++++++++ 2 files changed, 36 insertions(+) diff --git a/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.cpp b/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.cpp index f9bfce66c46..5743109773d 100644 --- a/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.cpp +++ b/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2023, Luke Wilde + * Copyright (c) 2024, Shannon Booth * * SPDX-License-Identifier: BSD-2-Clause */ @@ -33,4 +34,24 @@ WebIDL::CallbackType* BaseAudioContext::onstatechange() return event_handler_attribute(HTML::EventNames::statechange); } +// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-createbuffer +WebIDL::ExceptionOr BaseAudioContext::verify_audio_options_inside_nominal_range(JS::Realm& realm, WebIDL::UnsignedLong number_of_channels, WebIDL::UnsignedLong length, float sample_rate) +{ + // A NotSupportedError exception MUST be thrown if any of the arguments is negative, zero, or outside its nominal range. + + if (number_of_channels == 0) + return WebIDL::NotSupportedError::create(realm, "Number of channels must not be '0'"_fly_string); + + if (number_of_channels > MAX_NUMBER_OF_CHANNELS) + return WebIDL::NotSupportedError::create(realm, "Number of channels is greater than allowed range"_fly_string); + + if (length == 0) + return WebIDL::NotSupportedError::create(realm, "Length of buffer must be at least 1"_fly_string); + + if (sample_rate < MIN_SAMPLE_RATE || sample_rate > MAX_SAMPLE_RATE) + return WebIDL::NotSupportedError::create(realm, "Sample rate is outside of allowed range"_fly_string); + + return {}; +} + } diff --git a/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.h b/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.h index a9e80dcd12b..36cb826c37e 100644 --- a/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.h +++ b/Userland/Libraries/LibWeb/WebAudio/BaseAudioContext.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2023, Luke Wilde + * Copyright (c) 2024, Shannon Booth * * SPDX-License-Identifier: BSD-2-Clause */ @@ -8,6 +9,7 @@ #include #include +#include namespace Web::WebAudio { @@ -18,6 +20,17 @@ class BaseAudioContext : public DOM::EventTarget { public: virtual ~BaseAudioContext() override; + // https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-createbuffer-numberofchannels + // > An implementation MUST support at least 32 channels. + // Other browsers appear to only allow 32 channels - so let's limit ourselves to that too. + static constexpr WebIDL::UnsignedLong MAX_NUMBER_OF_CHANNELS { 32 }; + + // https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-createbuffer-samplerate + // > An implementation MUST support sample rates in at least the range 8000 to 96000. + // This doesn't seem consistent between browsers. We use what firefox accepts from testing BaseAudioContext.createAudioBuffer. + static constexpr float MIN_SAMPLE_RATE { 8000 }; + static constexpr float MAX_SAMPLE_RATE { 192000 }; + float sample_rate() const { return m_sample_rate; } double current_time() const { return m_current_time; } Bindings::AudioContextState state() const { return m_control_thread_state; } @@ -29,6 +42,8 @@ public: void set_control_state(Bindings::AudioContextState state) { m_control_thread_state = state; } void set_rendering_state(Bindings::AudioContextState state) { m_rendering_thread_state = state; } + static WebIDL::ExceptionOr verify_audio_options_inside_nominal_range(JS::Realm&, WebIDL::UnsignedLong number_of_channels, WebIDL::UnsignedLong length, float sample_rate); + protected: explicit BaseAudioContext(JS::Realm&);