diff --git a/Libraries/LibMedia/AudioBlock.h b/Libraries/LibMedia/AudioBlock.h index a4890f259c..84c7dc6054 100644 --- a/Libraries/LibMedia/AudioBlock.h +++ b/Libraries/LibMedia/AudioBlock.h @@ -10,20 +10,21 @@ #include #include #include -#include -#include #include +#include namespace Media { class AudioBlock { public: Audio::SampleSpecification const& sample_specification() const { return m_sample_specification; } - AK::Duration media_time_start() const { return m_media_time_start; } - AK::Duration media_time_duration() const { return m_media_time_duration; } - AK::Duration media_time_end() const { return m_media_time_start + m_media_time_duration; } - i64 first_frame_index() const { return m_first_frame_index; } - i64 end_frame_index() const { return saturating_add(m_first_frame_index, AK::clamp_to(frame_count())); } + AudioBlockTiming const& timing() const { return m_timing; } + AudioBlockTiming& timing() { return m_timing; } + AK::Duration media_time_start() const { return m_timing.media_time_start(); } + AK::Duration media_time_duration() const { return m_timing.media_time_duration(); } + AK::Duration media_time_end() const { return m_timing.media_time_end(); } + i64 first_frame_index() const { return m_timing.first_frame_index(); } + i64 end_frame_index() const { return m_timing.end_frame_index(); } Span channel_data(size_t channel) { VERIFY(channel < channel_count()); @@ -46,9 +47,7 @@ public: void clear() { m_sample_specification = {}; - m_media_time_start = {}; - m_media_time_duration = {}; - m_first_frame_index = 0; + m_timing.clear(); m_frame_count = 0; } void initialize(Audio::SampleSpecification sample_specification, AK::Duration media_time_start, size_t frame_count) @@ -57,11 +56,9 @@ public: VERIFY(frame_count <= NumericLimits::max()); VERIFY(!Checked::multiplication_would_overflow(frame_count, sample_specification.channel_count())); m_sample_specification = sample_specification; - m_media_time_start = media_time_start; - m_first_frame_index = media_time_start.to_time_units(1, sample_rate()); m_frame_count = frame_count; + m_timing.initialize(media_time_start, sample_rate(), AK::clamp_to(frame_count)); ensure_frame_capacity(frame_count); - recalculate_media_duration_from_frame_count(); } void initialize(Audio::SampleSpecification sample_specification, i64 first_frame_index, size_t frame_count) { @@ -69,17 +66,15 @@ public: VERIFY(frame_count <= NumericLimits::max()); VERIFY(!Checked::multiplication_would_overflow(frame_count, sample_specification.channel_count())); m_sample_specification = sample_specification; - m_first_frame_index = first_frame_index; - m_media_time_start = AK::Duration::from_time_units(first_frame_index, 1, sample_rate()); m_frame_count = frame_count; + m_timing.initialize(first_frame_index, sample_rate(), AK::clamp_to(frame_count)); ensure_frame_capacity(frame_count); - recalculate_media_duration_from_frame_count(); } void trim(size_t frame_count) { VERIFY(frame_count <= m_frame_count); m_frame_count = frame_count; - recalculate_media_duration_from_frame_count(); + m_timing.set_frame_count(sample_rate(), AK::clamp_to(frame_count)); } size_t copy_to_interleaved(Span destination, size_t source_frame_offset = 0) const { @@ -106,19 +101,17 @@ public: void set_first_frame_index(i64 first_frame_index) { VERIFY(!is_empty()); - m_first_frame_index = first_frame_index; - m_media_time_start = AK::Duration::from_time_units(first_frame_index, 1, sample_rate()); + m_timing.set_first_frame_index(first_frame_index, sample_rate()); } void set_media_time_start(AK::Duration media_time_start) { VERIFY(!is_empty()); - m_media_time_start = media_time_start; + m_timing.set_media_time_start(media_time_start); } void set_media_time_duration(AK::Duration media_time_duration) { VERIFY(!is_empty()); - VERIFY(!media_time_duration.is_negative()); - m_media_time_duration = media_time_duration; + m_timing.set_media_time_duration(media_time_duration); } bool is_empty() const { @@ -138,11 +131,6 @@ public: } private: - void recalculate_media_duration_from_frame_count() - { - m_media_time_duration = AK::Duration::from_time_units(AK::clamp_to(frame_count()), 1, sample_rate()); - } - size_t frame_capacity() const { if (!is_empty()) @@ -159,9 +147,7 @@ private: } Audio::SampleSpecification m_sample_specification; - AK::Duration m_media_time_start; - AK::Duration m_media_time_duration; - i64 m_first_frame_index { 0 }; + AudioBlockTiming m_timing; size_t m_frame_count { 0 }; FixedArray m_data; }; diff --git a/Libraries/LibMedia/AudioBlockTiming.h b/Libraries/LibMedia/AudioBlockTiming.h new file mode 100644 index 0000000000..ca5557119e --- /dev/null +++ b/Libraries/LibMedia/AudioBlockTiming.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2026-present, the Ladybird developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace Media { + +class AudioBlockTiming { +public: + AK::Duration media_time_start() const { return m_media_time_start; } + AK::Duration media_time_duration() const { return m_media_time_duration; } + AK::Duration media_time_end() const { return m_media_time_start + m_media_time_duration; } + + i64 first_frame_index() const { return m_first_frame_index; } + i64 frame_count() const { return m_frame_count; } + i64 end_frame_index() const { return saturating_add(m_first_frame_index, m_frame_count); } + + void clear() + { + m_media_time_start = {}; + m_media_time_duration = {}; + m_first_frame_index = 0; + m_frame_count = 0; + } + + void initialize(AK::Duration media_time_start, u32 sample_rate, i64 frame_count) + { + m_media_time_start = media_time_start; + m_first_frame_index = media_time_start.to_time_units(1, sample_rate); + m_frame_count = frame_count; + recalculate_media_duration_from_frame_count(sample_rate); + } + + void initialize(i64 first_frame_index, u32 sample_rate, i64 frame_count) + { + m_first_frame_index = first_frame_index; + m_media_time_start = AK::Duration::from_time_units(first_frame_index, 1, sample_rate); + m_frame_count = frame_count; + recalculate_media_duration_from_frame_count(sample_rate); + } + + void set_frame_count(u32 sample_rate, i64 frame_count) + { + m_frame_count = frame_count; + recalculate_media_duration_from_frame_count(sample_rate); + } + + void set_first_frame_index(i64 first_frame_index, u32 sample_rate) + { + m_first_frame_index = first_frame_index; + m_media_time_start = AK::Duration::from_time_units(first_frame_index, 1, sample_rate); + } + + void set_media_time_start(AK::Duration media_time_start) { m_media_time_start = media_time_start; } + void set_media_time_duration(AK::Duration media_time_duration) + { + VERIFY(!media_time_duration.is_negative()); + m_media_time_duration = media_time_duration; + } + +private: + void recalculate_media_duration_from_frame_count(u32 sample_rate) + { + m_media_time_duration = AK::Duration::from_time_units(m_frame_count, 1, sample_rate); + } + + AK::Duration m_media_time_start; + AK::Duration m_media_time_duration; + i64 m_first_frame_index { 0 }; + i64 m_frame_count { 0 }; +}; + +}