LibMedia: Move AudioBlock's timing info into a separate class

This will be used to account for playback rate in audio timing.
This commit is contained in:
Zaggy1024 2026-06-02 19:22:04 -05:00 committed by Gregory Bertilson
parent ee66ccb4af
commit 13d04e44c2
2 changed files with 96 additions and 30 deletions

View file

@ -10,20 +10,21 @@
#include <AK/FixedArray.h>
#include <AK/Math.h>
#include <AK/NumericLimits.h>
#include <AK/SaturatingMath.h>
#include <AK/Time.h>
#include <LibMedia/Audio/SampleSpecification.h>
#include <LibMedia/AudioBlockTiming.h>
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<i64>(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<float> 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<i64>::max());
VERIFY(!Checked<size_t>::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<i64>(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<i64>::max());
VERIFY(!Checked<size_t>::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<i64>(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<i64>(frame_count));
}
size_t copy_to_interleaved(Span<float> 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<i64>(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<float> m_data;
};

View file

@ -0,0 +1,80 @@
/*
* Copyright (c) 2026-present, the Ladybird developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Math.h>
#include <AK/SaturatingMath.h>
#include <AK/Time.h>
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 };
};
}