Compare commits

...

1 Commits

Author SHA1 Message Date
bunnei
f0fcb300de audio_renderer: Process audio data on another thread. 2020-01-22 19:57:04 -05:00
3 changed files with 66 additions and 9 deletions

View File

@@ -8,6 +8,7 @@
#include "audio_core/codec.h"
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/microprofile.h"
#include "core/core.h"
#include "core/hle/kernel/writable_event.h"
#include "core/memory.h"
@@ -17,6 +18,18 @@ namespace AudioCore {
constexpr u32 STREAM_SAMPLE_RATE{48000};
constexpr u32 STREAM_NUM_CHANNELS{2};
static void RunThread(AudioRenderer::SynchState& synch_state) {
MicroProfileOnThreadCreate("AudioRendererThread");
while (synch_state.is_running) {
auto next{synch_state.input_queue.PopWait()};
if (next.empty()) {
continue;
}
synch_state.output_queue.Push(synch_state.renderer.UpdateAudioRenderer(std::move(next)));
}
}
class AudioRenderer::VoiceState {
public:
bool IsPlaying() const {
@@ -72,12 +85,14 @@ private:
EffectOutStatus out_status{};
EffectInStatus info{};
};
AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing, Memory::Memory& memory_,
AudioRendererParameter params,
std::shared_ptr<Kernel::WritableEvent> buffer_event,
std::size_t instance_number)
: worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count),
effects(params.effect_count), memory{memory_} {
effects(params.effect_count), memory{memory_},
synch_state{*this}, thread{RunThread, std::ref(synch_state)} {
audio_out = std::make_unique<AudioCore::AudioOut>();
stream = audio_out->OpenStream(core_timing, STREAM_SAMPLE_RATE, STREAM_NUM_CHANNELS,
@@ -90,7 +105,12 @@ AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing, Memory::Memo
QueueMixedBuffer(2);
}
AudioRenderer::~AudioRenderer() = default;
AudioRenderer::~AudioRenderer() {
// Terminate thread
synch_state.is_running = false;
QueueUpdateAudioRenderer({}); // Queue empty data to force thread to wakeup
thread.join();
}
u32 AudioRenderer::GetSampleRate() const {
return worker_params.sample_rate;
@@ -113,7 +133,15 @@ static constexpr u32 VersionFromRevision(u32_le rev) {
return ((rev >> 24) & 0xff) - 0x30;
}
std::vector<u8> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_params) {
void AudioRenderer::QueueUpdateAudioRenderer(std::vector<u8>&& input_params) {
synch_state.input_queue.Push(std::move(input_params));
}
std::vector<u8> AudioRenderer::GetUpdateAudioRendererResult() {
return synch_state.output_queue.PopWait();
}
std::vector<u8> AudioRenderer::UpdateAudioRenderer(std::vector<u8>&& input_params) {
// Copy UpdateDataHeader struct
UpdateDataHeader config{};
std::memcpy(&config, input_params.data(), sizeof(UpdateDataHeader));

View File

@@ -6,12 +6,14 @@
#include <array>
#include <memory>
#include <thread>
#include <vector>
#include "audio_core/stream.h"
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/swap.h"
#include "common/threadsafe_queue.h"
#include "core/hle/kernel/object.h"
namespace Core::Timing {
@@ -226,14 +228,29 @@ public:
std::shared_ptr<Kernel::WritableEvent> buffer_event, std::size_t instance_number);
~AudioRenderer();
std::vector<u8> UpdateAudioRenderer(const std::vector<u8>& input_params);
void QueueMixedBuffer(Buffer::Tag tag);
void ReleaseAndQueueBuffers();
void QueueUpdateAudioRenderer(std::vector<u8>&& input_params);
std::vector<u8> GetUpdateAudioRendererResult();
std::vector<u8> UpdateAudioRenderer(std::vector<u8>&& input_params);
u32 GetSampleRate() const;
u32 GetSampleCount() const;
u32 GetMixBufferCount() const;
Stream::State GetStreamState() const;
/// Struct used to synchronize the AudioRenderer thread
struct SynchState final {
SynchState(AudioRenderer& renderer) : renderer{renderer} {}
std::atomic_bool is_running{true};
Common::SPSCQueue<std::vector<u8>> input_queue;
Common::SPSCQueue<std::vector<u8>> output_queue;
AudioRenderer& renderer;
};
private:
void QueueMixedBuffer(Buffer::Tag tag);
void ReleaseAndQueueBuffers();
private:
class EffectState;
class VoiceState;
@@ -245,6 +262,10 @@ private:
std::unique_ptr<AudioOut> audio_out;
StreamPtr stream;
Memory::Memory& memory;
// Used for thread management
SynchState synch_state;
std::thread thread;
};
} // namespace AudioCore

View File

@@ -92,9 +92,17 @@ private:
}
void RequestUpdateImpl(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Audio, "(STUBBED) called");
ctx.WriteBuffer(renderer->UpdateAudioRenderer(ctx.ReadBuffer()));
LOG_DEBUG(Service_Audio, "called");
renderer->QueueUpdateAudioRenderer(ctx.ReadBuffer());
ctx.SleepClientThread("IAudioRenderer::RequestUpdateImpl", UINT64_MAX,
[=](std::shared_ptr<Kernel::Thread> thread,
Kernel::HLERequestContext& ctx,
Kernel::ThreadWakeupReason reason) {
ctx.WriteBuffer(renderer->GetUpdateAudioRendererResult());
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
},
system_event.writable);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}