summaryrefslogtreecommitdiff
path: root/src/audio_core/audio_renderer.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2021-07-03 00:24:33 -0700
committerGravatar GitHub2021-07-03 00:24:33 -0700
commit2fc0a760f09c4557d476204ef558743e6f42bd71 (patch)
tree87be7a47b82b30d3a2805f47a77b72ef28805af6 /src/audio_core/audio_renderer.cpp
parentMerge pull request #6459 from lat9nq/ubuntu-fixes (diff)
parentFix XC2/VOEZ crashing, add audio looping and a few misc fixes (diff)
downloadyuzu-2fc0a760f09c4557d476204ef558743e6f42bd71.tar.gz
yuzu-2fc0a760f09c4557d476204ef558743e6f42bd71.tar.xz
yuzu-2fc0a760f09c4557d476204ef558743e6f42bd71.zip
Merge pull request #6498 from Kelebek1/Audio
[audio_core] Decouple audio update and processing, and process at variable rate
Diffstat (limited to 'src/audio_core/audio_renderer.cpp')
-rw-r--r--src/audio_core/audio_renderer.cpp62
1 files changed, 43 insertions, 19 deletions
diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp
index 80ffddb10..ccd5ca6cc 100644
--- a/src/audio_core/audio_renderer.cpp
+++ b/src/audio_core/audio_renderer.cpp
@@ -12,6 +12,7 @@
12#include "audio_core/voice_context.h" 12#include "audio_core/voice_context.h"
13#include "common/logging/log.h" 13#include "common/logging/log.h"
14#include "common/settings.h" 14#include "common/settings.h"
15#include "core/core_timing.h"
15#include "core/memory.h" 16#include "core/memory.h"
16 17
17namespace { 18namespace {
@@ -68,7 +69,9 @@ namespace {
68} // namespace 69} // namespace
69 70
70namespace AudioCore { 71namespace AudioCore {
71AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing, Core::Memory::Memory& memory_, 72constexpr s32 NUM_BUFFERS = 2;
73
74AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_,
72 AudioCommon::AudioRendererParameter params, 75 AudioCommon::AudioRendererParameter params,
73 Stream::ReleaseCallback&& release_callback, 76 Stream::ReleaseCallback&& release_callback,
74 std::size_t instance_number) 77 std::size_t instance_number)
@@ -77,7 +80,8 @@ AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing, Core::Memory
77 sink_context(params.sink_count), splitter_context(), 80 sink_context(params.sink_count), splitter_context(),
78 voices(params.voice_count), memory{memory_}, 81 voices(params.voice_count), memory{memory_},
79 command_generator(worker_params, voice_context, mix_context, splitter_context, effect_context, 82 command_generator(worker_params, voice_context, mix_context, splitter_context, effect_context,
80 memory) { 83 memory),
84 core_timing{core_timing_} {
81 behavior_info.SetUserRevision(params.revision); 85 behavior_info.SetUserRevision(params.revision);
82 splitter_context.Initialize(behavior_info, params.splitter_count, 86 splitter_context.Initialize(behavior_info, params.splitter_count,
83 params.num_splitter_send_channels); 87 params.num_splitter_send_channels);
@@ -86,16 +90,27 @@ AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing, Core::Memory
86 stream = audio_out->OpenStream( 90 stream = audio_out->OpenStream(
87 core_timing, params.sample_rate, AudioCommon::STREAM_NUM_CHANNELS, 91 core_timing, params.sample_rate, AudioCommon::STREAM_NUM_CHANNELS,
88 fmt::format("AudioRenderer-Instance{}", instance_number), std::move(release_callback)); 92 fmt::format("AudioRenderer-Instance{}", instance_number), std::move(release_callback));
89 audio_out->StartStream(stream); 93 process_event = Core::Timing::CreateEvent(
90 94 fmt::format("AudioRenderer-Instance{}-Process", instance_number),
91 QueueMixedBuffer(0); 95 [this](std::uintptr_t, std::chrono::nanoseconds) { ReleaseAndQueueBuffers(); });
92 QueueMixedBuffer(1); 96 for (s32 i = 0; i < NUM_BUFFERS; ++i) {
93 QueueMixedBuffer(2); 97 QueueMixedBuffer(i);
94 QueueMixedBuffer(3); 98 }
95} 99}
96 100
97AudioRenderer::~AudioRenderer() = default; 101AudioRenderer::~AudioRenderer() = default;
98 102
103ResultCode AudioRenderer::Start() {
104 audio_out->StartStream(stream);
105 ReleaseAndQueueBuffers();
106 return ResultSuccess;
107}
108
109ResultCode AudioRenderer::Stop() {
110 audio_out->StopStream(stream);
111 return ResultSuccess;
112}
113
99u32 AudioRenderer::GetSampleRate() const { 114u32 AudioRenderer::GetSampleRate() const {
100 return worker_params.sample_rate; 115 return worker_params.sample_rate;
101} 116}
@@ -114,7 +129,7 @@ Stream::State AudioRenderer::GetStreamState() const {
114 129
115ResultCode AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_params, 130ResultCode AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_params,
116 std::vector<u8>& output_params) { 131 std::vector<u8>& output_params) {
117 132 std::scoped_lock lock{mutex};
118 InfoUpdater info_updater{input_params, output_params, behavior_info}; 133 InfoUpdater info_updater{input_params, output_params, behavior_info};
119 134
120 if (!info_updater.UpdateBehaviorInfo(behavior_info)) { 135 if (!info_updater.UpdateBehaviorInfo(behavior_info)) {
@@ -194,9 +209,6 @@ ResultCode AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_param
194 LOG_ERROR(Audio, "Audio buffers were not consumed!"); 209 LOG_ERROR(Audio, "Audio buffers were not consumed!");
195 return AudioCommon::Audren::ERR_INVALID_PARAMETERS; 210 return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
196 } 211 }
197
198 ReleaseAndQueueBuffers();
199
200 return ResultSuccess; 212 return ResultSuccess;
201} 213}
202 214
@@ -220,10 +232,8 @@ void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) {
220 command_generator.PostCommand(); 232 command_generator.PostCommand();
221 // Base sample size 233 // Base sample size
222 std::size_t BUFFER_SIZE{worker_params.sample_count}; 234 std::size_t BUFFER_SIZE{worker_params.sample_count};
223 // Samples 235 // Samples, making sure to clear
224 std::vector<s16> buffer(BUFFER_SIZE * stream->GetNumChannels()); 236 std::vector<s16> buffer(BUFFER_SIZE * stream->GetNumChannels(), 0);
225 // Make sure to clear our samples
226 std::memset(buffer.data(), 0, buffer.size() * sizeof(s16));
227 237
228 if (sink_context.InUse()) { 238 if (sink_context.InUse()) {
229 const auto stream_channel_count = stream->GetNumChannels(); 239 const auto stream_channel_count = stream->GetNumChannels();
@@ -315,10 +325,24 @@ void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) {
315} 325}
316 326
317void AudioRenderer::ReleaseAndQueueBuffers() { 327void AudioRenderer::ReleaseAndQueueBuffers() {
318 const auto released_buffers{audio_out->GetTagsAndReleaseBuffers(stream)}; 328 if (!stream->IsPlaying()) {
319 for (const auto& tag : released_buffers) { 329 return;
320 QueueMixedBuffer(tag);
321 } 330 }
331
332 {
333 std::scoped_lock lock{mutex};
334 const auto released_buffers{audio_out->GetTagsAndReleaseBuffers(stream)};
335 for (const auto& tag : released_buffers) {
336 QueueMixedBuffer(tag);
337 }
338 }
339
340 const f32 sample_rate = static_cast<f32>(GetSampleRate());
341 const f32 sample_count = static_cast<f32>(GetSampleCount());
342 const f32 consume_rate = sample_rate / (sample_count * (sample_count / 240));
343 const s32 ms = (1000 / static_cast<s32>(consume_rate)) - 1;
344 const std::chrono::milliseconds next_event_time(std::max(ms / NUM_BUFFERS, 1));
345 core_timing.ScheduleEvent(next_event_time, process_event, {});
322} 346}
323 347
324} // namespace AudioCore 348} // namespace AudioCore