From 17ae65cedc1d811b2473b7ffd5338b3dbe917868 Mon Sep 17 00:00:00 2001 From: Shannon Booth Date: Sun, 26 May 2024 16:33:27 +1200 Subject: [PATCH] LibWeb: Implement AudioBuffer.copyToChannel --- .../WebAudio/AudioBuffer-copyToChannel.txt | 9 +++ .../WebAudio/AudioBuffer-copyToChannel.html | 75 +++++++++++++++++++ .../Libraries/LibWeb/WebAudio/AudioBuffer.cpp | 28 ++++++- .../Libraries/LibWeb/WebAudio/AudioBuffer.h | 2 +- 4 files changed, 109 insertions(+), 5 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/WebAudio/AudioBuffer-copyToChannel.txt create mode 100644 Tests/LibWeb/Text/input/WebAudio/AudioBuffer-copyToChannel.html diff --git a/Tests/LibWeb/Text/expected/WebAudio/AudioBuffer-copyToChannel.txt b/Tests/LibWeb/Text/expected/WebAudio/AudioBuffer-copyToChannel.txt new file mode 100644 index 00000000000..deaf4b6322b --- /dev/null +++ b/Tests/LibWeb/Text/expected/WebAudio/AudioBuffer-copyToChannel.txt @@ -0,0 +1,9 @@ +Error calling copyToChannel: IndexSizeError: Channel index is out of range +Error calling copyToChannel: TypeError: Not an object of type Float32Array +5,5,5,5,5,5,5 +1,1,1,1,1,1,1 +1,1,1,1,1,1,1 +1,1,1,1,1,1,1 +2,2,3,3,3,3,3 +2,2,3,3,3,3,3 +Done. diff --git a/Tests/LibWeb/Text/input/WebAudio/AudioBuffer-copyToChannel.html b/Tests/LibWeb/Text/input/WebAudio/AudioBuffer-copyToChannel.html new file mode 100644 index 00000000000..2ba85faf1da --- /dev/null +++ b/Tests/LibWeb/Text/input/WebAudio/AudioBuffer-copyToChannel.html @@ -0,0 +1,75 @@ + + diff --git a/Userland/Libraries/LibWeb/WebAudio/AudioBuffer.cpp b/Userland/Libraries/LibWeb/WebAudio/AudioBuffer.cpp index c39b800fa9d..b9ae09f79fa 100644 --- a/Userland/Libraries/LibWeb/WebAudio/AudioBuffer.cpp +++ b/Userland/Libraries/LibWeb/WebAudio/AudioBuffer.cpp @@ -105,11 +105,31 @@ WebIDL::ExceptionOr AudioBuffer::copy_from_channel(JS::Handle AudioBuffer::copy_to_channel(JS::Handle&, WebIDL::UnsignedLong channel_number, WebIDL::UnsignedLong buffer_offset) const +WebIDL::ExceptionOr AudioBuffer::copy_to_channel(JS::Handle const& source, WebIDL::UnsignedLong channel_number, WebIDL::UnsignedLong buffer_offset) { - (void)channel_number; - (void)buffer_offset; - return WebIDL::NotSupportedError::create(realm(), "FIXME: Implement AudioBuffer:copy_to_channel:"_fly_string); + // The copyToChannel() method copies the samples to the specified channel of the AudioBuffer from the source array. + // + // A UnknownError may be thrown if source cannot be copied to the buffer. + // + // Let buffer be the AudioBuffer with Nb frames, let Nf be the number of elements in the source array, and k be the value + // of bufferOffset. Then the number of frames copied from source to the buffer is max(0,min(Nb−k,Nf)). If this is less than Nf, + // then the remaining elements of buffer are not modified. + auto& vm = this->vm(); + + if (!is(*source->raw_object())) + return vm.throw_completion(JS::ErrorType::NotAnObjectOfType, "Float32Array"); + auto const& float32_array = static_cast(*source->raw_object()); + + auto channel = TRY(get_channel_data(channel_number)); + + auto channel_length = channel->data().size(); + if (buffer_offset >= channel_length) + return {}; + + u32 count = min(float32_array.data().size(), channel_length - buffer_offset); + float32_array.data().slice(0, count).copy_to(channel->data().slice(buffer_offset, count)); + + return {}; } AudioBuffer::AudioBuffer(JS::Realm& realm, AudioBufferOptions const& options) diff --git a/Userland/Libraries/LibWeb/WebAudio/AudioBuffer.h b/Userland/Libraries/LibWeb/WebAudio/AudioBuffer.h index 205a807fff6..3bb8a735c8a 100644 --- a/Userland/Libraries/LibWeb/WebAudio/AudioBuffer.h +++ b/Userland/Libraries/LibWeb/WebAudio/AudioBuffer.h @@ -38,7 +38,7 @@ public: WebIDL::UnsignedLong number_of_channels() const; WebIDL::ExceptionOr> get_channel_data(WebIDL::UnsignedLong channel) const; WebIDL::ExceptionOr copy_from_channel(JS::Handle const&, WebIDL::UnsignedLong channel_number, WebIDL::UnsignedLong buffer_offset = 0) const; - WebIDL::ExceptionOr copy_to_channel(JS::Handle&, WebIDL::UnsignedLong channel_number, WebIDL::UnsignedLong buffer_offset = 0) const; + WebIDL::ExceptionOr copy_to_channel(JS::Handle const&, WebIDL::UnsignedLong channel_number, WebIDL::UnsignedLong buffer_offset = 0); private: explicit AudioBuffer(JS::Realm&, AudioBufferOptions const&);