Kernel: Use ByteRingBuffer with audio buffers

This commit is contained in:
Bananymous 2026-03-23 22:12:40 +02:00
parent 35e2a70de0
commit dedeebbfbe
4 changed files with 32 additions and 48 deletions

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <kernel/Device/Device.h> #include <kernel/Device/Device.h>
#include <kernel/Memory/ByteRingBuffer.h>
#include <kernel/PCI.h> #include <kernel/PCI.h>
namespace Kernel namespace Kernel
@ -16,6 +17,7 @@ namespace Kernel
protected: protected:
AudioController(); AudioController();
BAN::ErrorOr<void> initialize();
virtual void handle_new_data() = 0; virtual void handle_new_data() = 0;
@ -27,7 +29,7 @@ namespace Kernel
virtual BAN::ErrorOr<void> set_current_pin(uint32_t) = 0; virtual BAN::ErrorOr<void> set_current_pin(uint32_t) = 0;
bool can_read_impl() const override { return false; } bool can_read_impl() const override { return false; }
bool can_write_impl() const override { SpinLockGuard _(m_spinlock); return m_sample_data_size < m_sample_data_capacity; } bool can_write_impl() const override { SpinLockGuard _(m_spinlock); return !m_sample_data->full(); }
bool has_error_impl() const override { return false; } bool has_error_impl() const override { return false; }
bool has_hungup_impl() const override { return false; } bool has_hungup_impl() const override { return false; }
@ -40,9 +42,7 @@ namespace Kernel
mutable SpinLock m_spinlock; mutable SpinLock m_spinlock;
static constexpr size_t m_sample_data_capacity = 1 << 20; static constexpr size_t m_sample_data_capacity = 1 << 20;
uint8_t m_sample_data[m_sample_data_capacity]; BAN::UniqPtr<ByteRingBuffer> m_sample_data;
size_t m_sample_data_head { 0 };
size_t m_sample_data_size { 0 };
private: private:
const dev_t m_rdev; const dev_t m_rdev;

View File

@ -118,6 +118,8 @@ namespace Kernel
BAN::ErrorOr<void> AC97AudioController::initialize() BAN::ErrorOr<void> AC97AudioController::initialize()
{ {
TRY(AudioController::initialize());
m_pci_device.enable_bus_mastering(); m_pci_device.enable_bus_mastering();
m_mixer = TRY(m_pci_device.allocate_bar_region(0)); m_mixer = TRY(m_pci_device.allocate_bar_region(0));
@ -203,23 +205,22 @@ namespace Kernel
if (next_bld_head == m_bdl_tail) if (next_bld_head == m_bdl_tail)
break; break;
const size_t sample_data_tail = (m_sample_data_head + m_sample_data_capacity - m_sample_data_size) % m_sample_data_capacity; const size_t sample_frames = BAN::Math::min(m_sample_data->size() / get_channels() / sizeof(uint16_t), m_samples_per_entry / get_channels());
if (sample_frames == 0)
const size_t max_memcpy = BAN::Math::min(m_sample_data_size, m_sample_data_capacity - sample_data_tail);
const size_t samples = BAN::Math::min(max_memcpy / 2, m_samples_per_entry);
if (samples == 0)
break; break;
const size_t copy_total_bytes = sample_frames * get_channels() * sizeof(uint16_t);
auto& entry = reinterpret_cast<AC97::BufferDescriptorListEntry*>(m_bdl_region->vaddr())[m_bdl_head]; auto& entry = reinterpret_cast<AC97::BufferDescriptorListEntry*>(m_bdl_region->vaddr())[m_bdl_head];
entry.samples = samples; entry.samples = sample_frames * get_channels();
entry.flags = (1 << 15); entry.flags = (1 << 15);
memcpy( memcpy(
reinterpret_cast<void*>(m_bdl_region->paddr_to_vaddr(entry.address)), reinterpret_cast<void*>(m_bdl_region->paddr_to_vaddr(entry.address)),
&m_sample_data[sample_data_tail], m_sample_data->get_data().data(),
samples * 2 copy_total_bytes
); );
m_sample_data_size -= samples * 2; m_sample_data->pop(copy_total_bytes);
lvi = m_bdl_head; lvi = m_bdl_head;
m_bdl_head = next_bld_head; m_bdl_head = next_bld_head;

View File

@ -53,34 +53,28 @@ namespace Kernel
return {}; return {};
} }
BAN::ErrorOr<void> AudioController::initialize()
{
m_sample_data = TRY(ByteRingBuffer::create(m_sample_data_capacity));
return {};
}
BAN::ErrorOr<size_t> AudioController::write_impl(off_t, BAN::ConstByteSpan buffer) BAN::ErrorOr<size_t> AudioController::write_impl(off_t, BAN::ConstByteSpan buffer)
{ {
SpinLockGuard lock_guard(m_spinlock); SpinLockGuard lock_guard(m_spinlock);
while (m_sample_data_size >= m_sample_data_capacity) while (m_sample_data->full())
{ {
SpinLockGuardAsMutex smutex(lock_guard); SpinLockGuardAsMutex smutex(lock_guard);
TRY(Thread::current().block_or_eintr_indefinite(m_sample_data_blocker, &smutex)); TRY(Thread::current().block_or_eintr_indefinite(m_sample_data_blocker, &smutex));
} }
size_t nwritten = 0; const size_t to_copy = BAN::Math::min(buffer.size(), m_sample_data->free());
while (nwritten < buffer.size()) m_sample_data->push(buffer.slice(0, to_copy));
{
if (m_sample_data_size >= m_sample_data_capacity)
break;
const size_t max_memcpy = BAN::Math::min(m_sample_data_capacity - m_sample_data_size, m_sample_data_capacity - m_sample_data_head);
const size_t to_copy = BAN::Math::min(buffer.size() - nwritten, max_memcpy);
memcpy(m_sample_data + m_sample_data_head, buffer.data() + nwritten, to_copy);
nwritten += to_copy;
m_sample_data_head = (m_sample_data_head + to_copy) % m_sample_data_capacity;
m_sample_data_size += to_copy;
}
handle_new_data(); handle_new_data();
return nwritten; return to_copy;
} }
BAN::ErrorOr<long> AudioController::ioctl_impl(int cmd, void* arg) BAN::ErrorOr<long> AudioController::ioctl_impl(int cmd, void* arg)
@ -97,9 +91,9 @@ namespace Kernel
case SND_GET_BUFFERSZ: case SND_GET_BUFFERSZ:
{ {
SpinLockGuard _(m_spinlock); SpinLockGuard _(m_spinlock);
*static_cast<uint32_t*>(arg) = m_sample_data_size; *static_cast<uint32_t*>(arg) = m_sample_data->size();
if (cmd == SND_RESET_BUFFER) if (cmd == SND_RESET_BUFFER)
m_sample_data_size = 0; m_sample_data->pop(m_sample_data->size());
return 0; return 0;
} }
case SND_GET_TOTAL_PINS: case SND_GET_TOTAL_PINS:

View File

@ -25,6 +25,8 @@ namespace Kernel
BAN::ErrorOr<void> HDAudioFunctionGroup::initialize() BAN::ErrorOr<void> HDAudioFunctionGroup::initialize()
{ {
TRY(AudioController::initialize());
if constexpr(DEBUG_HDAUDIO) if constexpr(DEBUG_HDAUDIO)
{ {
const auto widget_to_string = const auto widget_to_string =
@ -483,30 +485,18 @@ namespace Kernel
while ((m_bdl_head + 1) % m_bdl_entry_count != m_bdl_tail) while ((m_bdl_head + 1) % m_bdl_entry_count != m_bdl_tail)
{ {
const size_t sample_data_tail = (m_sample_data_head + m_sample_data_capacity - m_sample_data_size) % m_sample_data_capacity; const size_t sample_frames = BAN::Math::min(m_sample_data->size() / get_channels() / sizeof(uint16_t), m_bdl_entry_sample_frames);
const size_t sample_frames = BAN::Math::min(m_sample_data_size / get_channels() / sizeof(uint16_t), m_bdl_entry_sample_frames);
if (sample_frames == 0) if (sample_frames == 0)
break; break;
const size_t copy_total_bytes = sample_frames * get_channels() * sizeof(uint16_t); const size_t copy_total_bytes = sample_frames * get_channels() * sizeof(uint16_t);
const size_t copy_before_wrap = BAN::Math::min(copy_total_bytes, m_sample_data_capacity - sample_data_tail);
memcpy( memcpy(
reinterpret_cast<void*>(m_bdl_region->vaddr() + m_bdl_head * bdl_entry_bytes), reinterpret_cast<void*>(m_bdl_region->vaddr() + m_bdl_head * bdl_entry_bytes),
&m_sample_data[sample_data_tail], m_sample_data->get_data().data(),
copy_before_wrap copy_total_bytes
); );
if (copy_before_wrap < copy_total_bytes)
{
memcpy(
reinterpret_cast<void*>(m_bdl_region->vaddr() + m_bdl_head * bdl_entry_bytes + copy_before_wrap),
&m_sample_data[0],
copy_total_bytes - copy_before_wrap
);
}
if (copy_total_bytes < bdl_entry_bytes) if (copy_total_bytes < bdl_entry_bytes)
{ {
memset( memset(
@ -516,8 +506,7 @@ namespace Kernel
); );
} }
m_sample_data_size -= copy_total_bytes; m_sample_data->pop(copy_total_bytes);
m_bdl_head = (m_bdl_head + 1) % m_bdl_entry_count; m_bdl_head = (m_bdl_head + 1) % m_bdl_entry_count;
} }