Kernel: Use ByteRingBuffer with audio buffers
This commit is contained in:
parent
35e2a70de0
commit
dedeebbfbe
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue