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

LibAudio: Add a Serenity implementation of PlaybackStream

This implementation is very naive compared to the PulseAudio one.

Instead of using a callback implemented by the audio server connection
to push audio to the buffer, we have to poll on a timer to check when
we need to push the audio buffers. Implementing cross-process condition
variables into the audio queue class could allow us to avoid polling,
which may prove beneficial to CPU usage.

Audio timestamps will be accurate to the number of samples available,
but will count in increments of about 100ms and run ahead of the actual
audio being pushed to the device by the server.

Buffer underruns are completely ignored for now as well, since the
`AudioServer` has no way to know how many samples are actually written
in a single audio buffer.
This commit is contained in:
Zaggy1024 2023-08-02 19:05:47 -05:00 committed by Andrew Kaster
parent 2caf68fd03
commit bb156f8133
7 changed files with 185 additions and 3 deletions

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2023, Gregory Bertilson <zaggy1024@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibAudio/ConnectionToServer.h>
#include <LibAudio/PlaybackStream.h>
namespace Audio {
class PlaybackStreamSerenity final
: public PlaybackStream {
public:
static ErrorOr<NonnullRefPtr<PlaybackStream>> create(OutputState initial_state, u32 sample_rate, u8 channels, u32 target_latency_ms, AudioDataRequestCallback&& data_request_callback);
virtual void set_underrun_callback(Function<void()>) override;
virtual NonnullRefPtr<Core::ThreadedPromise<Duration>> resume() override;
virtual NonnullRefPtr<Core::ThreadedPromise<void>> drain_buffer_and_suspend() override;
virtual NonnullRefPtr<Core::ThreadedPromise<void>> discard_buffer_and_suspend() override;
virtual ErrorOr<Duration> total_time_played() override;
virtual NonnullRefPtr<Core::ThreadedPromise<void>> set_volume(double) override;
private:
PlaybackStreamSerenity(NonnullRefPtr<ConnectionToServer>, NonnullRefPtr<Core::Timer> polling_timer, AudioDataRequestCallback&& data_request_callback);
void fill_buffers();
NonnullRefPtr<ConnectionToServer> m_connection;
size_t m_number_of_samples_enqueued { 0 };
NonnullRefPtr<Core::Timer> m_polling_timer;
AudioDataRequestCallback m_data_request_callback;
bool m_paused { false };
};
}