Browse Source

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%
Andreas Kling 6 years ago
parent
commit
15afc88ffe

+ 7 - 0
Libraries/LibAudio/ABuffer.h

@@ -39,6 +39,13 @@ struct ASample {
             right = -1;
             right = -1;
     }
     }
 
 
+    void scale(int percent)
+    {
+        float pct = (float)percent / 100.0;
+        left *= pct;
+        right *= pct;
+    }
+
     ASample& operator+=(const ASample& other)
     ASample& operator+=(const ASample& other)
     {
     {
         left += other.left;
         left += other.left;

+ 16 - 0
Libraries/LibAudio/AClientConnection.cpp

@@ -30,3 +30,19 @@ void AClientConnection::enqueue(const ABuffer& buffer)
         sleep(1);
         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);
+}

+ 3 - 0
Libraries/LibAudio/AClientConnection.h

@@ -12,4 +12,7 @@ public:
 
 
     virtual void handshake() override;
     virtual void handshake() override;
     void enqueue(const ABuffer&);
     void enqueue(const ABuffer&);
+
+    int get_main_mix_volume();
+    void set_main_mix_volume(int);
 };
 };

+ 6 - 0
Libraries/LibAudio/ASAPI.h

@@ -7,11 +7,14 @@ struct ASAPI_ServerMessage {
         PlayingBuffer,
         PlayingBuffer,
         FinishedPlayingBuffer,
         FinishedPlayingBuffer,
         EnqueueBufferResponse,
         EnqueueBufferResponse,
+        DidGetMainMixVolume,
+        DidSetMainMixVolume,
     };
     };
 
 
     Type type { Type::Invalid };
     Type type { Type::Invalid };
     unsigned extra_size { 0 };
     unsigned extra_size { 0 };
     bool success { true };
     bool success { true };
+    int value { 0 };
 
 
     union {
     union {
         struct {
         struct {
@@ -29,10 +32,13 @@ struct ASAPI_ClientMessage {
         Invalid,
         Invalid,
         Greeting,
         Greeting,
         EnqueueBuffer,
         EnqueueBuffer,
+        GetMainMixVolume,
+        SetMainMixVolume,
     };
     };
 
 
     Type type { Type::Invalid };
     Type type { Type::Invalid };
     unsigned extra_size { 0 };
     unsigned extra_size { 0 };
+    int value { 0 };
 
 
     union {
     union {
         struct {
         struct {

+ 14 - 0
Servers/AudioServer/ASClientConnection.cpp

@@ -60,6 +60,20 @@ bool ASClientConnection::handle_message(const ASAPI_ClientMessage& message, cons
         post_message(reply);
         post_message(reply);
         break;
         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:
     case ASAPI_ClientMessage::Type::Invalid:
     default:
     default:
         dbgprintf("ASClientConnection: Unexpected message ID %d\n", int(message.type));
         dbgprintf("ASClientConnection: Unexpected message ID %d\n", int(message.type));

+ 2 - 0
Servers/AudioServer/ASMixer.cpp

@@ -71,6 +71,8 @@ void ASMixer::mix()
 
 
         for (int i = 0; i < mixed_buffer_length; ++i) {
         for (int i = 0; i < mixed_buffer_length; ++i) {
             auto& mixed_sample = mixed_buffer[i];
             auto& mixed_sample = mixed_buffer[i];
+
+            mixed_sample.scale(m_main_volume);
             mixed_sample.clip();
             mixed_sample.clip();
 
 
             i16 out_sample;
             i16 out_sample;

+ 5 - 0
Servers/AudioServer/ASMixer.h

@@ -54,11 +54,16 @@ public:
 
 
     NonnullRefPtr<ASBufferQueue> create_queue(ASClientConnection&);
     NonnullRefPtr<ASBufferQueue> create_queue(ASClientConnection&);
 
 
+    int main_volume() const { return m_main_volume; }
+    void set_main_volume(int volume) { m_main_volume = volume; }
+
 private:
 private:
     Vector<NonnullRefPtr<ASBufferQueue>> m_pending_mixing;
     Vector<NonnullRefPtr<ASBufferQueue>> m_pending_mixing;
 
 
     CFile m_device;
     CFile m_device;
     CLock m_lock;
     CLock m_lock;
 
 
+    int m_main_volume { 100 };
+
     void mix();
     void mix();
 };
 };

+ 19 - 0
Userland/avol.cpp

@@ -0,0 +1,19 @@
+#include <LibAudio/ABuffer.h>
+#include <LibAudio/AClientConnection.h>
+#include <stdio.h>
+
+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;
+}