cubeb_audio: Replace output yield loop with condvar.

This commit is contained in:
squidbus 2024-12-26 23:29:03 -08:00
parent a4ef7771df
commit 42fb06d0f1
3 changed files with 29 additions and 25 deletions

View File

@ -93,7 +93,7 @@ static bool IsFormatFloat(const OrbisAudioOutParamFormat format) {
}
}
static int GetFormatNumChannels(const OrbisAudioOutParamFormat format) {
static u8 GetFormatNumChannels(const OrbisAudioOutParamFormat format) {
switch (format) {
case OrbisAudioOutParamFormat::S16Mono:
case OrbisAudioOutParamFormat::FloatMono:
@ -403,12 +403,14 @@ s32 PS4_SYSV_ABI sceAudioOutOpen(UserService::OrbisUserServiceUserId user_id,
}
port->type = port_type;
port->samples_num = length;
port->freq = sample_rate;
port->format = format;
port->is_float = IsFormatFloat(format);
port->channels_num = GetFormatNumChannels(format);
port->sample_size = GetFormatSampleSize(format);
port->channels_num = GetFormatNumChannels(format);
port->samples_num = length;
port->frame_size = port->sample_size * port->channels_num;
port->buffer_size = port->frame_size * port->samples_num;
port->freq = sample_rate;
port->volume.fill(SCE_AUDIO_OUT_VOLUME_0DB);
port->impl = audio->Open(*port);
@ -434,8 +436,7 @@ s32 PS4_SYSV_ABI sceAudioOutOutput(s32 handle, void* ptr) {
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
}
const size_t data_size = port.samples_num * port.sample_size * port.channels_num;
port.impl->Output(ptr, data_size);
port.impl->Output(ptr, port.buffer_size);
return ORBIS_OK;
}

View File

@ -62,14 +62,16 @@ struct OrbisAudioOutPortState {
struct PortOut {
std::unique_ptr<PortBackend> impl{};
u32 samples_num;
u32 freq;
OrbisAudioOutParamFormat format;
OrbisAudioOutPort type;
int channels_num;
OrbisAudioOutParamFormat format;
bool is_float;
std::array<int, 8> volume;
u8 sample_size;
u8 channels_num;
u32 samples_num;
u32 frame_size;
u32 buffer_size;
u32 freq;
std::array<int, 8> volume;
};
int PS4_SYSV_ABI sceAudioOutDeviceIdOpen();

View File

@ -1,7 +1,8 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <cstdarg>
#include <condition_variable>
#include <mutex>
#include <cubeb/cubeb.h>
#include "common/assert.h"
@ -16,8 +17,7 @@ constexpr int AUDIO_STREAM_BUFFER_THRESHOLD = 65536; // Define constant for buff
class CubebPortBackend : public PortBackend {
public:
CubebPortBackend(cubeb* ctx, const PortOut& port)
: frame_size(port.channels_num * port.sample_size),
buffer(static_cast<int>(port.samples_num * frame_size) * 4) {
: frame_size(port.frame_size), buffer(static_cast<int>(port.buffer_size) * 4) {
if (!ctx) {
return;
}
@ -36,7 +36,7 @@ public:
cubeb_stream_params stream_params = {
.format = port.is_float ? CUBEB_SAMPLE_FLOAT32LE : CUBEB_SAMPLE_S16LE,
.rate = port.freq,
.channels = static_cast<u32>(port.channels_num),
.channels = port.channels_num,
.layout = get_channel_layout(),
.prefs = CUBEB_STREAM_PREF_NONE,
};
@ -75,16 +75,10 @@ public:
void Output(void* ptr, size_t size) override {
auto* data = static_cast<u8*>(ptr);
while (size > 0) {
const auto queued = buffer.enqueue(data, static_cast<int>(size));
size -= queued;
data += queued;
if (size > 0) {
// If the data is too large for the ring buffer, yield execution and give it a
// chance to drain.
std::this_thread::yield();
}
}
std::unique_lock lock{buffer_mutex};
buffer_cv.wait(lock, [&] { return buffer.available_write() >= size; });
buffer.enqueue(data, static_cast<int>(size));
}
void SetVolume(const std::array<int, 8>& ch_volumes) override {
@ -106,7 +100,12 @@ private:
auto* stream_data = static_cast<CubebPortBackend*>(user_data);
const auto out_data = static_cast<u8*>(out);
const auto requested_size = static_cast<int>(num_frames * stream_data->frame_size);
std::unique_lock lock{stream_data->buffer_mutex};
const auto dequeued_size = stream_data->buffer.dequeue(out_data, requested_size);
lock.unlock();
stream_data->buffer_cv.notify_one();
if (dequeued_size < requested_size) {
// Need to fill remaining space with silence.
std::memset(out_data + dequeued_size, 0, requested_size - dequeued_size);
@ -133,6 +132,8 @@ private:
size_t frame_size;
ring_buffer_base<u8> buffer;
std::mutex buffer_mutex;
std::condition_variable buffer_cv;
cubeb_stream* stream{};
};