From 15afc88ffefa5b9641107834c87b8674c7fa3fa9 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 29 Jul 2019 19:06:58 +0200 Subject: [PATCH] AudioServer: Add a "main mix volume" and a simple program to get/set it Give the mixer a main volume value (percent) that we scale all the outgoing samples by (before clipping.) Also add a simple "avol" program for querying and setting the volume: - "avol" prints the current volume. - "avol 200" sets the main mix volume to 200% --- Libraries/LibAudio/ABuffer.h | 7 +++++++ Libraries/LibAudio/AClientConnection.cpp | 16 ++++++++++++++++ Libraries/LibAudio/AClientConnection.h | 3 +++ Libraries/LibAudio/ASAPI.h | 6 ++++++ Servers/AudioServer/ASClientConnection.cpp | 14 ++++++++++++++ Servers/AudioServer/ASMixer.cpp | 2 ++ Servers/AudioServer/ASMixer.h | 5 +++++ Userland/avol.cpp | 19 +++++++++++++++++++ 8 files changed, 72 insertions(+) create mode 100644 Userland/avol.cpp diff --git a/Libraries/LibAudio/ABuffer.h b/Libraries/LibAudio/ABuffer.h index a8a7d2a580..287c0a738f 100644 --- a/Libraries/LibAudio/ABuffer.h +++ b/Libraries/LibAudio/ABuffer.h @@ -39,6 +39,13 @@ struct ASample { right = -1; } + void scale(int percent) + { + float pct = (float)percent / 100.0; + left *= pct; + right *= pct; + } + ASample& operator+=(const ASample& other) { left += other.left; diff --git a/Libraries/LibAudio/AClientConnection.cpp b/Libraries/LibAudio/AClientConnection.cpp index d77a455c51..bc0eecaa7f 100644 --- a/Libraries/LibAudio/AClientConnection.cpp +++ b/Libraries/LibAudio/AClientConnection.cpp @@ -30,3 +30,19 @@ void AClientConnection::enqueue(const ABuffer& buffer) sleep(1); } } + +int AClientConnection::get_main_mix_volume() +{ + ASAPI_ClientMessage request; + request.type = ASAPI_ClientMessage::Type::GetMainMixVolume; + auto response = sync_request(request, ASAPI_ServerMessage::Type::DidGetMainMixVolume); + return response.value; +} + +void AClientConnection::set_main_mix_volume(int volume) +{ + ASAPI_ClientMessage request; + request.type = ASAPI_ClientMessage::Type::SetMainMixVolume; + request.value = volume; + sync_request(request, ASAPI_ServerMessage::Type::DidSetMainMixVolume); +} diff --git a/Libraries/LibAudio/AClientConnection.h b/Libraries/LibAudio/AClientConnection.h index 1a6c00abac..7f7047b99c 100644 --- a/Libraries/LibAudio/AClientConnection.h +++ b/Libraries/LibAudio/AClientConnection.h @@ -12,4 +12,7 @@ public: virtual void handshake() override; void enqueue(const ABuffer&); + + int get_main_mix_volume(); + void set_main_mix_volume(int); }; diff --git a/Libraries/LibAudio/ASAPI.h b/Libraries/LibAudio/ASAPI.h index 47da165de6..2915360ff3 100644 --- a/Libraries/LibAudio/ASAPI.h +++ b/Libraries/LibAudio/ASAPI.h @@ -7,11 +7,14 @@ struct ASAPI_ServerMessage { PlayingBuffer, FinishedPlayingBuffer, EnqueueBufferResponse, + DidGetMainMixVolume, + DidSetMainMixVolume, }; Type type { Type::Invalid }; unsigned extra_size { 0 }; bool success { true }; + int value { 0 }; union { struct { @@ -29,10 +32,13 @@ struct ASAPI_ClientMessage { Invalid, Greeting, EnqueueBuffer, + GetMainMixVolume, + SetMainMixVolume, }; Type type { Type::Invalid }; unsigned extra_size { 0 }; + int value { 0 }; union { struct { diff --git a/Servers/AudioServer/ASClientConnection.cpp b/Servers/AudioServer/ASClientConnection.cpp index f365feae72..94d30e00d2 100644 --- a/Servers/AudioServer/ASClientConnection.cpp +++ b/Servers/AudioServer/ASClientConnection.cpp @@ -60,6 +60,20 @@ bool ASClientConnection::handle_message(const ASAPI_ClientMessage& message, cons post_message(reply); break; } + case ASAPI_ClientMessage::Type::GetMainMixVolume: { + ASAPI_ServerMessage reply; + reply.type = ASAPI_ServerMessage::Type::DidGetMainMixVolume; + reply.value = m_mixer.main_volume(); + post_message(reply); + break; + } + case ASAPI_ClientMessage::Type::SetMainMixVolume: { + ASAPI_ServerMessage reply; + reply.type = ASAPI_ServerMessage::Type::DidSetMainMixVolume; + m_mixer.set_main_volume(message.value); + post_message(reply); + break; + } case ASAPI_ClientMessage::Type::Invalid: default: dbgprintf("ASClientConnection: Unexpected message ID %d\n", int(message.type)); diff --git a/Servers/AudioServer/ASMixer.cpp b/Servers/AudioServer/ASMixer.cpp index 77053bd7b7..f99b4c763a 100644 --- a/Servers/AudioServer/ASMixer.cpp +++ b/Servers/AudioServer/ASMixer.cpp @@ -71,6 +71,8 @@ void ASMixer::mix() for (int i = 0; i < mixed_buffer_length; ++i) { auto& mixed_sample = mixed_buffer[i]; + + mixed_sample.scale(m_main_volume); mixed_sample.clip(); i16 out_sample; diff --git a/Servers/AudioServer/ASMixer.h b/Servers/AudioServer/ASMixer.h index 8ddd8573bf..fbd9f101f1 100644 --- a/Servers/AudioServer/ASMixer.h +++ b/Servers/AudioServer/ASMixer.h @@ -54,11 +54,16 @@ public: NonnullRefPtr create_queue(ASClientConnection&); + int main_volume() const { return m_main_volume; } + void set_main_volume(int volume) { m_main_volume = volume; } + private: Vector> m_pending_mixing; CFile m_device; CLock m_lock; + int m_main_volume { 100 }; + void mix(); }; diff --git a/Userland/avol.cpp b/Userland/avol.cpp new file mode 100644 index 0000000000..7c10fea6eb --- /dev/null +++ b/Userland/avol.cpp @@ -0,0 +1,19 @@ +#include +#include +#include + +int main(int argc, char** argv) +{ + CEventLoop loop; + AClientConnection a_conn; + a_conn.handshake(); + + if (argc > 1) { + int new_volume = atoi(argv[1]); + a_conn.set_main_mix_volume(new_volume); + } + + int volume = a_conn.get_main_mix_volume(); + printf("Volume: %d\n", volume); + return 0; +}