1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 08:37:46 +00:00

AudioServer+LibAudio: Make mixing queue-based instead of buffer-based.

Each client connection now sets up an ASBufferQueue, which is basically a
queue of ABuffers. This allows us to immediately start streaming the next
pending buffer whenever our current buffer runs out of samples.

This makes the majority of the skippiness go away for me. :^)

Also get rid of the old PlayBuffer API, since we don't need it anymore.
This commit is contained in:
Andreas Kling 2019-07-28 21:27:18 +02:00
parent 66db6f4f92
commit be31e2232c
7 changed files with 78 additions and 112 deletions

View file

@ -2,6 +2,7 @@
#include <AK/ByteBuffer.h>
#include <AK/NonnullRefPtrVector.h>
#include <AK/Queue.h>
#include <AK/RefCounted.h>
#include <AK/WeakPtr.h>
#include <LibAudio/ABuffer.h>
@ -10,22 +11,52 @@
class ASClientConnection;
class ASBufferQueue : public RefCounted<ASBufferQueue> {
public:
explicit ASBufferQueue(ASClientConnection&);
~ASBufferQueue() {}
bool is_full() const { return m_queue.size() >= 3; }
void enqueue(NonnullRefPtr<ABuffer>&&);
bool get_next_sample(ASample& sample)
{
while (!m_current && !m_queue.is_empty())
m_current = m_queue.dequeue();
if (!m_current)
return false;
sample = m_current->samples()[m_position++];
if (m_position >= m_current->sample_count()) {
m_current = nullptr;
m_position = 0;
}
return true;
}
ASClientConnection* client() { return m_client.ptr(); }
void clear()
{
m_queue.clear();
m_position = 0;
}
private:
RefPtr<ABuffer> m_current;
Queue<NonnullRefPtr<ABuffer>> m_queue;
int m_position { 0 };
int m_playing_queued_buffer_id { -1 };
WeakPtr<ASClientConnection> m_client;
};
class ASMixer : public RefCounted<ASMixer> {
public:
ASMixer();
void queue(ASClientConnection&, const ABuffer&);
NonnullRefPtr<ASBufferQueue> create_queue(ASClientConnection&);
private:
struct ASMixerBuffer {
ASMixerBuffer(const NonnullRefPtr<ABuffer>&, ASClientConnection&);
NonnullRefPtr<ABuffer> buffer;
int pos { 0 };
bool done { false };
WeakPtr<ASClientConnection> m_client;
};
Vector<NonnullRefPtr<ASBufferQueue>> m_pending_mixing;
Vector<ASMixerBuffer> m_pending_mixing;
CFile m_device;
CLock m_lock;