1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 21:58:12 +00:00

Audio: Make basic streaming WAV playback work.

I had to solve a bunch of things simultaneously to make this work.
Refactor AWavLoader to be a streaming loader rather than a one-shot one.
The constructor parses the header, and if everything looks good, you can
repeatedly ask the AWavLoader for sample buffers until it runs out.

Also send a message from AudioServer when a buffer has finished playing.
That allows us to implement a blocking variant of play().

Use all of this in aplay to play WAV files chunk-at-a-time.
This is definitely not perfect and it's a little glitchy and skippy,
but I think it's a step in the right direction.
This commit is contained in:
Andreas Kling 2019-07-27 17:20:41 +02:00
parent a292d8cd5a
commit 426248098c
10 changed files with 88 additions and 64 deletions

View file

@ -1,8 +1,9 @@
#include <AK/BufferStream.h>
#include <AudioServer/ASClientConnection.h>
#include <AudioServer/ASMixer.h>
#include <LibAudio/ASAPI.h>
#include <LibCore/CThread.h>
#include <limits>
#include "ASMixer.h"
ASMixer::ASMixer()
: m_device("/dev/audio")
@ -19,11 +20,11 @@ ASMixer::ASMixer()
}, this);
}
void ASMixer::queue(ASClientConnection&, const ABuffer& buffer)
void ASMixer::queue(ASClientConnection& client, const ABuffer& buffer, int buffer_id)
{
ASSERT(buffer.size_in_bytes());
CLocker lock(m_lock);
m_pending_mixing.append(ASMixerBuffer(buffer));
m_pending_mixing.append(ASMixerBuffer(buffer, client, buffer_id));
}
void ASMixer::mix()
@ -75,8 +76,15 @@ void ASMixer::mix()
}
// clear it later
if (buffer.pos == samples.size())
if (buffer.pos == samples.size()) {
if (buffer.m_buffer_id && buffer.m_client) {
ASAPI_ServerMessage reply;
reply.type = ASAPI_ServerMessage::Type::FinishedPlayingBuffer;
reply.playing_buffer.buffer_id = buffer.m_buffer_id;
buffer.m_client->post_message(reply);
}
buffer.done = true;
}
}
// output the mixed stuff to the device
@ -108,3 +116,10 @@ void ASMixer::mix()
}
}
}
ASMixer::ASMixerBuffer::ASMixerBuffer(const NonnullRefPtr<ABuffer>& buf, ASClientConnection& client, int buffer_id)
: buffer(buf)
, m_client(client.make_weak_ptr())
, m_buffer_id(buffer_id)
{
}