diff --git a/kernel/include/kernel/Audio/Controller.h b/kernel/include/kernel/Audio/Controller.h index 367d191e..7fa8bbbd 100644 --- a/kernel/include/kernel/Audio/Controller.h +++ b/kernel/include/kernel/Audio/Controller.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include namespace Kernel @@ -16,6 +17,7 @@ namespace Kernel protected: AudioController(); + BAN::ErrorOr initialize(); virtual void handle_new_data() = 0; @@ -27,7 +29,7 @@ namespace Kernel virtual BAN::ErrorOr set_current_pin(uint32_t) = 0; 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_hungup_impl() const override { return false; } @@ -40,9 +42,7 @@ namespace Kernel mutable SpinLock m_spinlock; static constexpr size_t m_sample_data_capacity = 1 << 20; - uint8_t m_sample_data[m_sample_data_capacity]; - size_t m_sample_data_head { 0 }; - size_t m_sample_data_size { 0 }; + BAN::UniqPtr m_sample_data; private: const dev_t m_rdev; diff --git a/kernel/kernel/Audio/AC97/Controller.cpp b/kernel/kernel/Audio/AC97/Controller.cpp index b5c1e9a1..3eabfb46 100644 --- a/kernel/kernel/Audio/AC97/Controller.cpp +++ b/kernel/kernel/Audio/AC97/Controller.cpp @@ -118,6 +118,8 @@ namespace Kernel BAN::ErrorOr AC97AudioController::initialize() { + TRY(AudioController::initialize()); + m_pci_device.enable_bus_mastering(); m_mixer = TRY(m_pci_device.allocate_bar_region(0)); @@ -203,23 +205,22 @@ namespace Kernel if (next_bld_head == m_bdl_tail) 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 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) + 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) break; + const size_t copy_total_bytes = sample_frames * get_channels() * sizeof(uint16_t); + auto& entry = reinterpret_cast(m_bdl_region->vaddr())[m_bdl_head]; - entry.samples = samples; + entry.samples = sample_frames * get_channels(); entry.flags = (1 << 15); memcpy( reinterpret_cast(m_bdl_region->paddr_to_vaddr(entry.address)), - &m_sample_data[sample_data_tail], - samples * 2 + m_sample_data->get_data().data(), + copy_total_bytes ); - m_sample_data_size -= samples * 2; + m_sample_data->pop(copy_total_bytes); lvi = m_bdl_head; m_bdl_head = next_bld_head; diff --git a/kernel/kernel/Audio/Controller.cpp b/kernel/kernel/Audio/Controller.cpp index 940d21f1..017dc161 100644 --- a/kernel/kernel/Audio/Controller.cpp +++ b/kernel/kernel/Audio/Controller.cpp @@ -53,34 +53,28 @@ namespace Kernel return {}; } + BAN::ErrorOr AudioController::initialize() + { + m_sample_data = TRY(ByteRingBuffer::create(m_sample_data_capacity)); + return {}; + } + BAN::ErrorOr AudioController::write_impl(off_t, BAN::ConstByteSpan buffer) { SpinLockGuard lock_guard(m_spinlock); - while (m_sample_data_size >= m_sample_data_capacity) + while (m_sample_data->full()) { SpinLockGuardAsMutex smutex(lock_guard); TRY(Thread::current().block_or_eintr_indefinite(m_sample_data_blocker, &smutex)); } - size_t nwritten = 0; - while (nwritten < buffer.size()) - { - 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; - } + const size_t to_copy = BAN::Math::min(buffer.size(), m_sample_data->free()); + m_sample_data->push(buffer.slice(0, to_copy)); handle_new_data(); - return nwritten; + return to_copy; } BAN::ErrorOr AudioController::ioctl_impl(int cmd, void* arg) @@ -97,9 +91,9 @@ namespace Kernel case SND_GET_BUFFERSZ: { SpinLockGuard _(m_spinlock); - *static_cast(arg) = m_sample_data_size; + *static_cast(arg) = m_sample_data->size(); if (cmd == SND_RESET_BUFFER) - m_sample_data_size = 0; + m_sample_data->pop(m_sample_data->size()); return 0; } case SND_GET_TOTAL_PINS: diff --git a/kernel/kernel/Audio/HDAudio/AudioFunctionGroup.cpp b/kernel/kernel/Audio/HDAudio/AudioFunctionGroup.cpp index 230c775e..18f15e76 100644 --- a/kernel/kernel/Audio/HDAudio/AudioFunctionGroup.cpp +++ b/kernel/kernel/Audio/HDAudio/AudioFunctionGroup.cpp @@ -25,6 +25,8 @@ namespace Kernel BAN::ErrorOr HDAudioFunctionGroup::initialize() { + TRY(AudioController::initialize()); + if constexpr(DEBUG_HDAUDIO) { const auto widget_to_string = @@ -483,30 +485,18 @@ namespace Kernel 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) break; 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( reinterpret_cast(m_bdl_region->vaddr() + m_bdl_head * bdl_entry_bytes), - &m_sample_data[sample_data_tail], - copy_before_wrap + m_sample_data->get_data().data(), + copy_total_bytes ); - if (copy_before_wrap < copy_total_bytes) - { - memcpy( - reinterpret_cast(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) { 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; }