From 78e40ca353227fedc24c64dad5275e79eccc2029 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Wed, 19 Aug 2026 15:56:25 +0300 Subject: [PATCH] AudioServer: Add software volume control --- .../programs/AudioServer/AudioServer.cpp | 43 ++++++++++++------- userspace/programs/AudioServer/AudioServer.h | 1 + userspace/programs/AudioServer/main.cpp | 1 + 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/userspace/programs/AudioServer/AudioServer.cpp b/userspace/programs/AudioServer/AudioServer.cpp index 4cc9aef0..0a5c4c26 100644 --- a/userspace/programs/AudioServer/AudioServer.cpp +++ b/userspace/programs/AudioServer/AudioServer.cpp @@ -111,17 +111,18 @@ bool AudioServer::on_client_packet(int fd, LibAudio::Packet packet) { // NOTE: maybe we should map [0->100%] -> [min, 0] instead? + double hw_percent = 1.0; + const auto& volume = device().volume; - if (volume.min_mdB == volume.max_mdB) - response = 1000; - else + if (volume.min_mdB != volume.max_mdB) { - const double min_dB = volume.min_mdB / 1000.0; - const double max_dB = volume.max_mdB / 1000.0; - const double dB = volume.mdB / 1000.0; - const double percent = (BAN::Math::pow(10.0, (dB - min_dB) / (max_dB - min_dB)) - 1.0) / 9.0; - response = BAN::Math::round(percent * 1000.0); + const double min_mdB = volume.min_mdB; + const double max_mdB = volume.max_mdB; + hw_percent = (BAN::Math::pow(10.0, (device().volume.mdB - min_mdB) / (max_mdB - min_mdB)) - 1.0) / 9.0; } + + response = BAN::Math::round(device().volume_mult * hw_percent * 1000.0); + break; } case LibAudio::Packet::SetVolume: @@ -129,16 +130,24 @@ bool AudioServer::on_client_packet(int fd, LibAudio::Packet packet) // NOTE: maybe we should map [0->100%] -> [min, 0] instead? const auto& volume = device().volume; - const double min_dB = volume.min_mdB / 1000.0; - const double max_dB = volume.max_mdB / 1000.0; + const double min_mdB = volume.min_mdB; + const double max_mdB = volume.max_mdB; const double percent = packet.parameter / 1000.0; - const double dB = min_dB + (max_dB - min_dB) * BAN::Math::log10(1.0 + 9.0 * percent); + const int32_t mdB = BAN::Math::round(min_mdB + (max_mdB - min_mdB) * BAN::Math::log10(1.0 + 9.0 * percent)); - const int32_t mdB = BAN::Math::round(dB * 1000.0); if (ioctl(device().fd, SND_SET_VOLUME_MDB, &mdB) != 0) - dwarnln("Failed to set volume: {}", strerror(errno)); - else if (ioctl(device().fd, SND_GET_VOLUME_INFO, &device().volume) != 0) - dwarnln("Failed to query new volume: {}", strerror(errno)); + dwarnln("Failed to set hardware volume: {}", strerror(errno)); + + if (ioctl(device().fd, SND_GET_VOLUME_INFO, &device().volume) != 0) + { + dwarnln("Failed to query new hardware volume: {}", strerror(errno)); + device().volume_mult = 1.0; + } + else + { + const double hw_percent = (BAN::Math::pow(10.0, (device().volume.mdB - min_mdB) / (max_mdB - min_mdB)) - 1.0) / 9.0; + device().volume_mult = percent / hw_percent; + } break; } @@ -313,11 +322,13 @@ void AudioServer::send_samples() auto buffer = BAN::ByteSpan(static_cast(alloca(samples_to_send * sizeof(kernel_sample_t))), samples_to_send * sizeof(kernel_sample_t)); { + const double sample_mult = device().volume_mult * BAN::numeric_limits::max(); + auto sample_buffer = buffer.as_span(); for (size_t i = 0; i < samples_to_send; i++) { sample_buffer[i] = BAN::Math::clamp( - m_samples[m_samples_sent + i] * BAN::numeric_limits::max(), + sample_mult * m_samples[m_samples_sent + i], BAN::numeric_limits::min(), BAN::numeric_limits::max() ); diff --git a/userspace/programs/AudioServer/AudioServer.h b/userspace/programs/AudioServer/AudioServer.h index cf703f4b..039e14a2 100644 --- a/userspace/programs/AudioServer/AudioServer.h +++ b/userspace/programs/AudioServer/AudioServer.h @@ -17,6 +17,7 @@ struct AudioDevice uint32_t sample_rate; uint32_t total_pins; uint32_t current_pin; + double volume_mult; snd_volume_info volume; }; diff --git a/userspace/programs/AudioServer/main.cpp b/userspace/programs/AudioServer/main.cpp index aa3672e6..d219026c 100644 --- a/userspace/programs/AudioServer/main.cpp +++ b/userspace/programs/AudioServer/main.cpp @@ -60,6 +60,7 @@ static BAN::Optional initialize_audio_device(int fd) { AudioDevice result {}; result.fd = fd; + result.volume_mult = 1.0; if (ioctl(fd, SND_GET_CHANNELS, &result.channels) != 0) return {}; if (ioctl(fd, SND_GET_SAMPLE_RATE, &result.sample_rate) != 0)