summaryrefslogtreecommitdiff
path: root/src/audio_core
diff options
context:
space:
mode:
authorGravatar Levi2021-01-10 22:09:56 -0700
committerGravatar Levi2021-01-10 22:09:56 -0700
commit7a3c884e39fccfbb498b855080bffabc9ce2e7f1 (patch)
tree5056f9406dec188439cb0deb87603498243a9412 /src/audio_core
parentMore forgetting... duh (diff)
parentMerge pull request #5229 from Morph1984/fullscreen-opt (diff)
downloadyuzu-7a3c884e39fccfbb498b855080bffabc9ce2e7f1.tar.gz
yuzu-7a3c884e39fccfbb498b855080bffabc9ce2e7f1.tar.xz
yuzu-7a3c884e39fccfbb498b855080bffabc9ce2e7f1.zip
Merge remote-tracking branch 'upstream/master' into int-flags
Diffstat (limited to 'src/audio_core')
-rw-r--r--src/audio_core/CMakeLists.txt18
-rw-r--r--src/audio_core/algorithm/filter.cpp9
-rw-r--r--src/audio_core/algorithm/filter.h4
-rw-r--r--src/audio_core/algorithm/interpolate.cpp7
-rw-r--r--src/audio_core/audio_out.cpp4
-rw-r--r--src/audio_core/audio_out.h3
-rw-r--r--src/audio_core/audio_renderer.cpp131
-rw-r--r--src/audio_core/audio_renderer.h29
-rw-r--r--src/audio_core/behavior_info.cpp6
-rw-r--r--src/audio_core/behavior_info.h30
-rw-r--r--src/audio_core/buffer.h2
-rw-r--r--src/audio_core/codec.cpp5
-rw-r--r--src/audio_core/codec.h2
-rw-r--r--src/audio_core/command_generator.cpp47
-rw-r--r--src/audio_core/command_generator.h23
-rw-r--r--src/audio_core/common.h3
-rw-r--r--src/audio_core/cubeb_sink.cpp26
-rw-r--r--src/audio_core/effect_context.cpp68
-rw-r--r--src/audio_core/effect_context.h53
-rw-r--r--src/audio_core/info_updater.cpp37
-rw-r--r--src/audio_core/info_updater.h4
-rw-r--r--src/audio_core/memory_pool.cpp13
-rw-r--r--src/audio_core/memory_pool.h11
-rw-r--r--src/audio_core/mix_context.cpp4
-rw-r--r--src/audio_core/mix_context.h26
-rw-r--r--src/audio_core/sink_context.cpp20
-rw-r--r--src/audio_core/sink_context.h29
-rw-r--r--src/audio_core/splitter_context.cpp28
-rw-r--r--src/audio_core/splitter_context.h20
-rw-r--r--src/audio_core/stream.cpp31
-rw-r--r--src/audio_core/stream.h25
-rw-r--r--src/audio_core/voice_context.cpp16
-rw-r--r--src/audio_core/voice_context.h10
33 files changed, 431 insertions, 313 deletions
diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt
index cb00ef60e..d1d177b51 100644
--- a/src/audio_core/CMakeLists.txt
+++ b/src/audio_core/CMakeLists.txt
@@ -44,6 +44,24 @@ add_library(audio_core STATIC
44 44
45create_target_directory_groups(audio_core) 45create_target_directory_groups(audio_core)
46 46
47if (NOT MSVC)
48 target_compile_options(audio_core PRIVATE
49 -Werror=conversion
50 -Werror=ignored-qualifiers
51 -Werror=implicit-fallthrough
52 -Werror=reorder
53 -Werror=sign-compare
54 -Werror=shadow
55 -Werror=unused-parameter
56 -Werror=unused-variable
57
58 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter>
59 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable>
60
61 -Wno-sign-conversion
62 )
63endif()
64
47target_link_libraries(audio_core PUBLIC common core) 65target_link_libraries(audio_core PUBLIC common core)
48target_link_libraries(audio_core PRIVATE SoundTouch) 66target_link_libraries(audio_core PRIVATE SoundTouch)
49 67
diff --git a/src/audio_core/algorithm/filter.cpp b/src/audio_core/algorithm/filter.cpp
index f65bf64f7..01b8dff6b 100644
--- a/src/audio_core/algorithm/filter.cpp
+++ b/src/audio_core/algorithm/filter.cpp
@@ -31,8 +31,8 @@ Filter Filter::LowPass(double cutoff, double Q) {
31 31
32Filter::Filter() : Filter(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) {} 32Filter::Filter() : Filter(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) {}
33 33
34Filter::Filter(double a0, double a1, double a2, double b0, double b1, double b2) 34Filter::Filter(double a0_, double a1_, double a2_, double b0_, double b1_, double b2_)
35 : a1(a1 / a0), a2(a2 / a0), b0(b0 / a0), b1(b1 / a0), b2(b2 / a0) {} 35 : a1(a1_ / a0_), a2(a2_ / a0_), b0(b0_ / a0_), b1(b1_ / a0_), b2(b2_ / a0_) {}
36 36
37void Filter::Process(std::vector<s16>& signal) { 37void Filter::Process(std::vector<s16>& signal) {
38 const std::size_t num_frames = signal.size() / 2; 38 const std::size_t num_frames = signal.size() / 2;
@@ -55,7 +55,8 @@ void Filter::Process(std::vector<s16>& signal) {
55/// @param total_count The total number of biquads to be cascaded. 55/// @param total_count The total number of biquads to be cascaded.
56/// @param index 0-index of the biquad to calculate the Q value for. 56/// @param index 0-index of the biquad to calculate the Q value for.
57static double CascadingBiquadQ(std::size_t total_count, std::size_t index) { 57static double CascadingBiquadQ(std::size_t total_count, std::size_t index) {
58 const double pole = M_PI * (2 * index + 1) / (4.0 * total_count); 58 const auto pole =
59 M_PI * static_cast<double>(2 * index + 1) / (4.0 * static_cast<double>(total_count));
59 return 1.0 / (2.0 * std::cos(pole)); 60 return 1.0 / (2.0 * std::cos(pole));
60} 61}
61 62
@@ -68,7 +69,7 @@ CascadingFilter CascadingFilter::LowPass(double cutoff, std::size_t cascade_size
68} 69}
69 70
70CascadingFilter::CascadingFilter() = default; 71CascadingFilter::CascadingFilter() = default;
71CascadingFilter::CascadingFilter(std::vector<Filter> filters) : filters(std::move(filters)) {} 72CascadingFilter::CascadingFilter(std::vector<Filter> filters_) : filters(std::move(filters_)) {}
72 73
73void CascadingFilter::Process(std::vector<s16>& signal) { 74void CascadingFilter::Process(std::vector<s16>& signal) {
74 for (auto& filter : filters) { 75 for (auto& filter : filters) {
diff --git a/src/audio_core/algorithm/filter.h b/src/audio_core/algorithm/filter.h
index 3546d149b..a291fe79b 100644
--- a/src/audio_core/algorithm/filter.h
+++ b/src/audio_core/algorithm/filter.h
@@ -25,7 +25,7 @@ public:
25 /// Passthrough filter. 25 /// Passthrough filter.
26 Filter(); 26 Filter();
27 27
28 Filter(double a0, double a1, double a2, double b0, double b1, double b2); 28 Filter(double a0_, double a1_, double a2_, double b0_, double b1_, double b2_);
29 29
30 void Process(std::vector<s16>& signal); 30 void Process(std::vector<s16>& signal);
31 31
@@ -51,7 +51,7 @@ public:
51 /// Passthrough. 51 /// Passthrough.
52 CascadingFilter(); 52 CascadingFilter();
53 53
54 explicit CascadingFilter(std::vector<Filter> filters); 54 explicit CascadingFilter(std::vector<Filter> filters_);
55 55
56 void Process(std::vector<s16>& signal); 56 void Process(std::vector<s16>& signal);
57 57
diff --git a/src/audio_core/algorithm/interpolate.cpp b/src/audio_core/algorithm/interpolate.cpp
index 689a54508..3b4144e21 100644
--- a/src/audio_core/algorithm/interpolate.cpp
+++ b/src/audio_core/algorithm/interpolate.cpp
@@ -146,7 +146,7 @@ std::vector<s16> Interpolate(InterpolationState& state, std::vector<s16> input,
146 return {}; 146 return {};
147 147
148 if (ratio <= 0) { 148 if (ratio <= 0) {
149 LOG_CRITICAL(Audio, "Nonsensical interpolation ratio {}", ratio); 149 LOG_ERROR(Audio, "Nonsensical interpolation ratio {}", ratio);
150 return input; 150 return input;
151 } 151 }
152 152
@@ -164,7 +164,8 @@ std::vector<s16> Interpolate(InterpolationState& state, std::vector<s16> input,
164 const std::size_t num_frames{input.size() / 2}; 164 const std::size_t num_frames{input.size() / 2};
165 165
166 std::vector<s16> output; 166 std::vector<s16> output;
167 output.reserve(static_cast<std::size_t>(input.size() / ratio + InterpolationState::taps)); 167 output.reserve(static_cast<std::size_t>(static_cast<double>(input.size()) / ratio +
168 InterpolationState::taps));
168 169
169 for (std::size_t frame{}; frame < num_frames; ++frame) { 170 for (std::size_t frame{}; frame < num_frames; ++frame) {
170 const std::size_t lut_index{(state.fraction >> 8) * InterpolationState::taps}; 171 const std::size_t lut_index{(state.fraction >> 8) * InterpolationState::taps};
@@ -217,7 +218,7 @@ void Resample(s32* output, const s32* input, s32 pitch, s32& fraction, std::size
217 const auto l2 = lut[lut_index + 2]; 218 const auto l2 = lut[lut_index + 2];
218 const auto l3 = lut[lut_index + 3]; 219 const auto l3 = lut[lut_index + 3];
219 220
220 const auto s0 = static_cast<s32>(input[index]); 221 const auto s0 = static_cast<s32>(input[index + 0]);
221 const auto s1 = static_cast<s32>(input[index + 1]); 222 const auto s1 = static_cast<s32>(input[index + 1]);
222 const auto s2 = static_cast<s32>(input[index + 2]); 223 const auto s2 = static_cast<s32>(input[index + 2]);
223 const auto s3 = static_cast<s32>(input[index + 3]); 224 const auto s3 = static_cast<s32>(input[index + 3]);
diff --git a/src/audio_core/audio_out.cpp b/src/audio_core/audio_out.cpp
index 8619a3f03..fe3a898ad 100644
--- a/src/audio_core/audio_out.cpp
+++ b/src/audio_core/audio_out.cpp
@@ -43,6 +43,10 @@ std::vector<Buffer::Tag> AudioOut::GetTagsAndReleaseBuffers(StreamPtr stream,
43 return stream->GetTagsAndReleaseBuffers(max_count); 43 return stream->GetTagsAndReleaseBuffers(max_count);
44} 44}
45 45
46std::vector<Buffer::Tag> AudioOut::GetTagsAndReleaseBuffers(StreamPtr stream) {
47 return stream->GetTagsAndReleaseBuffers();
48}
49
46void AudioOut::StartStream(StreamPtr stream) { 50void AudioOut::StartStream(StreamPtr stream) {
47 stream->Play(); 51 stream->Play();
48} 52}
diff --git a/src/audio_core/audio_out.h b/src/audio_core/audio_out.h
index b07588287..6ce08cd0d 100644
--- a/src/audio_core/audio_out.h
+++ b/src/audio_core/audio_out.h
@@ -31,6 +31,9 @@ public:
31 /// Returns a vector of recently released buffers specified by tag for the specified stream 31 /// Returns a vector of recently released buffers specified by tag for the specified stream
32 std::vector<Buffer::Tag> GetTagsAndReleaseBuffers(StreamPtr stream, std::size_t max_count); 32 std::vector<Buffer::Tag> GetTagsAndReleaseBuffers(StreamPtr stream, std::size_t max_count);
33 33
34 /// Returns a vector of all recently released buffers specified by tag for the specified stream
35 std::vector<Buffer::Tag> GetTagsAndReleaseBuffers(StreamPtr stream);
36
34 /// Starts an audio stream for playback 37 /// Starts an audio stream for playback
35 void StartStream(StreamPtr stream); 38 void StartStream(StreamPtr stream);
36 39
diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp
index 56dc892b1..d2ce8c814 100644
--- a/src/audio_core/audio_renderer.cpp
+++ b/src/audio_core/audio_renderer.cpp
@@ -2,43 +2,90 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <limits>
5#include <vector> 6#include <vector>
6#include "audio_core/algorithm/interpolate.h" 7
7#include "audio_core/audio_out.h" 8#include "audio_core/audio_out.h"
8#include "audio_core/audio_renderer.h" 9#include "audio_core/audio_renderer.h"
9#include "audio_core/codec.h"
10#include "audio_core/common.h" 10#include "audio_core/common.h"
11#include "audio_core/info_updater.h" 11#include "audio_core/info_updater.h"
12#include "audio_core/voice_context.h" 12#include "audio_core/voice_context.h"
13#include "common/assert.h"
14#include "common/logging/log.h" 13#include "common/logging/log.h"
15#include "core/core.h"
16#include "core/hle/kernel/writable_event.h"
17#include "core/memory.h" 14#include "core/memory.h"
18#include "core/settings.h" 15#include "core/settings.h"
19 16
17namespace {
18[[nodiscard]] static constexpr s16 ClampToS16(s32 value) {
19 return static_cast<s16>(std::clamp(value, s32{std::numeric_limits<s16>::min()},
20 s32{std::numeric_limits<s16>::max()}));
21}
22
23[[nodiscard]] static constexpr s16 Mix2To1(s16 l_channel, s16 r_channel) {
24 // Mix 50% from left and 50% from right channel
25 constexpr float l_mix_amount = 50.0f / 100.0f;
26 constexpr float r_mix_amount = 50.0f / 100.0f;
27 return ClampToS16(static_cast<s32>((static_cast<float>(l_channel) * l_mix_amount) +
28 (static_cast<float>(r_channel) * r_mix_amount)));
29}
30
31[[nodiscard]] static constexpr std::tuple<s16, s16> Mix6To2(s16 fl_channel, s16 fr_channel,
32 s16 fc_channel,
33 [[maybe_unused]] s16 lf_channel,
34 s16 bl_channel, s16 br_channel) {
35 // Front channels are mixed 36.94%, Center channels are mixed to be 26.12% & the back channels
36 // are mixed to be 36.94%
37
38 constexpr float front_mix_amount = 36.94f / 100.0f;
39 constexpr float center_mix_amount = 26.12f / 100.0f;
40 constexpr float back_mix_amount = 36.94f / 100.0f;
41
42 // Mix 50% from left and 50% from right channel
43 const auto left = front_mix_amount * static_cast<float>(fl_channel) +
44 center_mix_amount * static_cast<float>(fc_channel) +
45 back_mix_amount * static_cast<float>(bl_channel);
46
47 const auto right = front_mix_amount * static_cast<float>(fr_channel) +
48 center_mix_amount * static_cast<float>(fc_channel) +
49 back_mix_amount * static_cast<float>(br_channel);
50
51 return {ClampToS16(static_cast<s32>(left)), ClampToS16(static_cast<s32>(right))};
52}
53
54[[nodiscard]] static constexpr std::tuple<s16, s16> Mix6To2WithCoefficients(
55 s16 fl_channel, s16 fr_channel, s16 fc_channel, s16 lf_channel, s16 bl_channel, s16 br_channel,
56 const std::array<float_le, 4>& coeff) {
57 const auto left =
58 static_cast<float>(fl_channel) * coeff[0] + static_cast<float>(fc_channel) * coeff[1] +
59 static_cast<float>(lf_channel) * coeff[2] + static_cast<float>(bl_channel) * coeff[0];
60
61 const auto right =
62 static_cast<float>(fr_channel) * coeff[0] + static_cast<float>(fc_channel) * coeff[1] +
63 static_cast<float>(lf_channel) * coeff[2] + static_cast<float>(br_channel) * coeff[0];
64
65 return {ClampToS16(static_cast<s32>(left)), ClampToS16(static_cast<s32>(right))};
66}
67
68} // namespace
69
20namespace AudioCore { 70namespace AudioCore {
21AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing, Core::Memory::Memory& memory_, 71AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing, Core::Memory::Memory& memory_,
22 AudioCommon::AudioRendererParameter params, 72 AudioCommon::AudioRendererParameter params,
23 std::shared_ptr<Kernel::WritableEvent> buffer_event, 73 Stream::ReleaseCallback&& release_callback,
24 std::size_t instance_number) 74 std::size_t instance_number)
25 : worker_params{params}, buffer_event{buffer_event}, 75 : worker_params{params}, memory_pool_info(params.effect_count + params.voice_count * 4),
26 memory_pool_info(params.effect_count + params.voice_count * 4),
27 voice_context(params.voice_count), effect_context(params.effect_count), mix_context(), 76 voice_context(params.voice_count), effect_context(params.effect_count), mix_context(),
28 sink_context(params.sink_count), splitter_context(), 77 sink_context(params.sink_count), splitter_context(),
29 voices(params.voice_count), memory{memory_}, 78 voices(params.voice_count), memory{memory_},
30 command_generator(worker_params, voice_context, mix_context, splitter_context, effect_context, 79 command_generator(worker_params, voice_context, mix_context, splitter_context, effect_context,
31 memory), 80 memory) {
32 temp_mix_buffer(AudioCommon::TOTAL_TEMP_MIX_SIZE) {
33 behavior_info.SetUserRevision(params.revision); 81 behavior_info.SetUserRevision(params.revision);
34 splitter_context.Initialize(behavior_info, params.splitter_count, 82 splitter_context.Initialize(behavior_info, params.splitter_count,
35 params.num_splitter_send_channels); 83 params.num_splitter_send_channels);
36 mix_context.Initialize(behavior_info, params.submix_count + 1, params.effect_count); 84 mix_context.Initialize(behavior_info, params.submix_count + 1, params.effect_count);
37 audio_out = std::make_unique<AudioCore::AudioOut>(); 85 audio_out = std::make_unique<AudioCore::AudioOut>();
38 stream = 86 stream = audio_out->OpenStream(
39 audio_out->OpenStream(core_timing, params.sample_rate, AudioCommon::STREAM_NUM_CHANNELS, 87 core_timing, params.sample_rate, AudioCommon::STREAM_NUM_CHANNELS,
40 fmt::format("AudioRenderer-Instance{}", instance_number), 88 fmt::format("AudioRenderer-Instance{}", instance_number), std::move(release_callback));
41 [=]() { buffer_event->Signal(); });
42 audio_out->StartStream(stream); 89 audio_out->StartStream(stream);
43 90
44 QueueMixedBuffer(0); 91 QueueMixedBuffer(0);
@@ -65,10 +112,6 @@ Stream::State AudioRenderer::GetStreamState() const {
65 return stream->GetState(); 112 return stream->GetState();
66} 113}
67 114
68static constexpr s16 ClampToS16(s32 value) {
69 return static_cast<s16>(std::clamp(value, -32768, 32767));
70}
71
72ResultCode AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_params, 115ResultCode AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_params,
73 std::vector<u8>& output_params) { 116 std::vector<u8>& output_params) {
74 117
@@ -107,8 +150,8 @@ ResultCode AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_param
107 } 150 }
108 } 151 }
109 152
110 auto mix_result = info_updater.UpdateMixes(mix_context, worker_params.mix_buffer_count, 153 const auto mix_result = info_updater.UpdateMixes(mix_context, worker_params.mix_buffer_count,
111 splitter_context, effect_context); 154 splitter_context, effect_context);
112 155
113 if (mix_result.IsError()) { 156 if (mix_result.IsError()) {
114 LOG_ERROR(Audio, "Failed to update mix parameters"); 157 LOG_ERROR(Audio, "Failed to update mix parameters");
@@ -197,20 +240,22 @@ void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) {
197 for (std::size_t i = 0; i < BUFFER_SIZE; i++) { 240 for (std::size_t i = 0; i < BUFFER_SIZE; i++) {
198 if (channel_count == 1) { 241 if (channel_count == 1) {
199 const auto sample = ClampToS16(mix_buffers[0][i]); 242 const auto sample = ClampToS16(mix_buffers[0][i]);
200 buffer[i * stream_channel_count + 0] = sample; 243
201 if (stream_channel_count > 1) { 244 // Place sample in all channels
202 buffer[i * stream_channel_count + 1] = sample; 245 for (u32 channel = 0; channel < stream_channel_count; channel++) {
246 buffer[i * stream_channel_count + channel] = sample;
203 } 247 }
248
204 if (stream_channel_count == 6) { 249 if (stream_channel_count == 6) {
205 buffer[i * stream_channel_count + 2] = sample; 250 // Output stream has a LF channel, mute it!
206 buffer[i * stream_channel_count + 4] = sample; 251 buffer[i * stream_channel_count + 3] = 0;
207 buffer[i * stream_channel_count + 5] = sample;
208 } 252 }
253
209 } else if (channel_count == 2) { 254 } else if (channel_count == 2) {
210 const auto l_sample = ClampToS16(mix_buffers[0][i]); 255 const auto l_sample = ClampToS16(mix_buffers[0][i]);
211 const auto r_sample = ClampToS16(mix_buffers[1][i]); 256 const auto r_sample = ClampToS16(mix_buffers[1][i]);
212 if (stream_channel_count == 1) { 257 if (stream_channel_count == 1) {
213 buffer[i * stream_channel_count + 0] = l_sample; 258 buffer[i * stream_channel_count + 0] = Mix2To1(l_sample, r_sample);
214 } else if (stream_channel_count == 2) { 259 } else if (stream_channel_count == 2) {
215 buffer[i * stream_channel_count + 0] = l_sample; 260 buffer[i * stream_channel_count + 0] = l_sample;
216 buffer[i * stream_channel_count + 1] = r_sample; 261 buffer[i * stream_channel_count + 1] = r_sample;
@@ -218,8 +263,8 @@ void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) {
218 buffer[i * stream_channel_count + 0] = l_sample; 263 buffer[i * stream_channel_count + 0] = l_sample;
219 buffer[i * stream_channel_count + 1] = r_sample; 264 buffer[i * stream_channel_count + 1] = r_sample;
220 265
221 buffer[i * stream_channel_count + 2] = 266 // Combine both left and right channels to the center channel
222 ClampToS16((static_cast<s32>(l_sample) + static_cast<s32>(r_sample)) / 2); 267 buffer[i * stream_channel_count + 2] = Mix2To1(l_sample, r_sample);
223 268
224 buffer[i * stream_channel_count + 4] = l_sample; 269 buffer[i * stream_channel_count + 4] = l_sample;
225 buffer[i * stream_channel_count + 5] = r_sample; 270 buffer[i * stream_channel_count + 5] = r_sample;
@@ -234,17 +279,25 @@ void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) {
234 const auto br_sample = ClampToS16(mix_buffers[5][i]); 279 const auto br_sample = ClampToS16(mix_buffers[5][i]);
235 280
236 if (stream_channel_count == 1) { 281 if (stream_channel_count == 1) {
237 buffer[i * stream_channel_count + 0] = fc_sample; 282 // Games seem to ignore the center channel half the time, we use the front left
283 // and right channel for mixing as that's where majority of the audio goes
284 buffer[i * stream_channel_count + 0] = Mix2To1(fl_sample, fr_sample);
238 } else if (stream_channel_count == 2) { 285 } else if (stream_channel_count == 2) {
239 buffer[i * stream_channel_count + 0] = 286 // Mix all channels into 2 channels
240 static_cast<s16>(0.3694f * static_cast<float>(fl_sample) + 287 if (sink_context.HasDownMixingCoefficients()) {
241 0.2612f * static_cast<float>(fc_sample) + 288 const auto [left, right] = Mix6To2WithCoefficients(
242 0.3694f * static_cast<float>(bl_sample)); 289 fl_sample, fr_sample, fc_sample, lf_sample, bl_sample, br_sample,
243 buffer[i * stream_channel_count + 1] = 290 sink_context.GetDownmixCoefficients());
244 static_cast<s16>(0.3694f * static_cast<float>(fr_sample) + 291 buffer[i * stream_channel_count + 0] = left;
245 0.2612f * static_cast<float>(fc_sample) + 292 buffer[i * stream_channel_count + 1] = right;
246 0.3694f * static_cast<float>(br_sample)); 293 } else {
294 const auto [left, right] = Mix6To2(fl_sample, fr_sample, fc_sample,
295 lf_sample, bl_sample, br_sample);
296 buffer[i * stream_channel_count + 0] = left;
297 buffer[i * stream_channel_count + 1] = right;
298 }
247 } else if (stream_channel_count == 6) { 299 } else if (stream_channel_count == 6) {
300 // Pass through
248 buffer[i * stream_channel_count + 0] = fl_sample; 301 buffer[i * stream_channel_count + 0] = fl_sample;
249 buffer[i * stream_channel_count + 1] = fr_sample; 302 buffer[i * stream_channel_count + 1] = fr_sample;
250 buffer[i * stream_channel_count + 2] = fc_sample; 303 buffer[i * stream_channel_count + 2] = fc_sample;
@@ -262,7 +315,7 @@ void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) {
262} 315}
263 316
264void AudioRenderer::ReleaseAndQueueBuffers() { 317void AudioRenderer::ReleaseAndQueueBuffers() {
265 const auto released_buffers{audio_out->GetTagsAndReleaseBuffers(stream, 2)}; 318 const auto released_buffers{audio_out->GetTagsAndReleaseBuffers(stream)};
266 for (const auto& tag : released_buffers) { 319 for (const auto& tag : released_buffers) {
267 QueueMixedBuffer(tag); 320 QueueMixedBuffer(tag);
268 } 321 }
diff --git a/src/audio_core/audio_renderer.h b/src/audio_core/audio_renderer.h
index 2bca795ba..18567f618 100644
--- a/src/audio_core/audio_renderer.h
+++ b/src/audio_core/audio_renderer.h
@@ -21,53 +21,41 @@
21#include "common/common_funcs.h" 21#include "common/common_funcs.h"
22#include "common/common_types.h" 22#include "common/common_types.h"
23#include "common/swap.h" 23#include "common/swap.h"
24#include "core/hle/kernel/object.h"
25#include "core/hle/result.h" 24#include "core/hle/result.h"
26 25
27namespace Core::Timing { 26namespace Core::Timing {
28class CoreTiming; 27class CoreTiming;
29} 28}
30 29
31namespace Kernel {
32class WritableEvent;
33}
34
35namespace Core::Memory { 30namespace Core::Memory {
36class Memory; 31class Memory;
37} 32}
38 33
39namespace AudioCore { 34namespace AudioCore {
40using DSPStateHolder = std::array<VoiceState*, 6>; 35using DSPStateHolder = std::array<VoiceState*, AudioCommon::MAX_CHANNEL_COUNT>;
41 36
42class AudioOut; 37class AudioOut;
43 38
44struct RendererInfo {
45 u64_le elasped_frame_count{};
46 INSERT_PADDING_WORDS(2);
47};
48static_assert(sizeof(RendererInfo) == 0x10, "RendererInfo is an invalid size");
49
50class AudioRenderer { 39class AudioRenderer {
51public: 40public:
52 AudioRenderer(Core::Timing::CoreTiming& core_timing, Core::Memory::Memory& memory_, 41 AudioRenderer(Core::Timing::CoreTiming& core_timing, Core::Memory::Memory& memory_,
53 AudioCommon::AudioRendererParameter params, 42 AudioCommon::AudioRendererParameter params,
54 std::shared_ptr<Kernel::WritableEvent> buffer_event, std::size_t instance_number); 43 Stream::ReleaseCallback&& release_callback, std::size_t instance_number);
55 ~AudioRenderer(); 44 ~AudioRenderer();
56 45
57 ResultCode UpdateAudioRenderer(const std::vector<u8>& input_params, 46 [[nodiscard]] ResultCode UpdateAudioRenderer(const std::vector<u8>& input_params,
58 std::vector<u8>& output_params); 47 std::vector<u8>& output_params);
59 void QueueMixedBuffer(Buffer::Tag tag); 48 void QueueMixedBuffer(Buffer::Tag tag);
60 void ReleaseAndQueueBuffers(); 49 void ReleaseAndQueueBuffers();
61 u32 GetSampleRate() const; 50 [[nodiscard]] u32 GetSampleRate() const;
62 u32 GetSampleCount() const; 51 [[nodiscard]] u32 GetSampleCount() const;
63 u32 GetMixBufferCount() const; 52 [[nodiscard]] u32 GetMixBufferCount() const;
64 Stream::State GetStreamState() const; 53 [[nodiscard]] Stream::State GetStreamState() const;
65 54
66private: 55private:
67 BehaviorInfo behavior_info{}; 56 BehaviorInfo behavior_info{};
68 57
69 AudioCommon::AudioRendererParameter worker_params; 58 AudioCommon::AudioRendererParameter worker_params;
70 std::shared_ptr<Kernel::WritableEvent> buffer_event;
71 std::vector<ServerMemoryPoolInfo> memory_pool_info; 59 std::vector<ServerMemoryPoolInfo> memory_pool_info;
72 VoiceContext voice_context; 60 VoiceContext voice_context;
73 EffectContext effect_context; 61 EffectContext effect_context;
@@ -80,7 +68,6 @@ private:
80 Core::Memory::Memory& memory; 68 Core::Memory::Memory& memory;
81 CommandGenerator command_generator; 69 CommandGenerator command_generator;
82 std::size_t elapsed_frame_count{}; 70 std::size_t elapsed_frame_count{};
83 std::vector<s32> temp_mix_buffer{};
84}; 71};
85 72
86} // namespace AudioCore 73} // namespace AudioCore
diff --git a/src/audio_core/behavior_info.cpp b/src/audio_core/behavior_info.cpp
index 5d62adb0b..3c2e3e6f1 100644
--- a/src/audio_core/behavior_info.cpp
+++ b/src/audio_core/behavior_info.cpp
@@ -57,15 +57,15 @@ bool BehaviorInfo::IsLongSizePreDelaySupported() const {
57 return AudioCommon::IsRevisionSupported(3, user_revision); 57 return AudioCommon::IsRevisionSupported(3, user_revision);
58} 58}
59 59
60bool BehaviorInfo::IsAudioRenererProcessingTimeLimit80PercentSupported() const { 60bool BehaviorInfo::IsAudioRendererProcessingTimeLimit80PercentSupported() const {
61 return AudioCommon::IsRevisionSupported(5, user_revision); 61 return AudioCommon::IsRevisionSupported(5, user_revision);
62} 62}
63 63
64bool BehaviorInfo::IsAudioRenererProcessingTimeLimit75PercentSupported() const { 64bool BehaviorInfo::IsAudioRendererProcessingTimeLimit75PercentSupported() const {
65 return AudioCommon::IsRevisionSupported(4, user_revision); 65 return AudioCommon::IsRevisionSupported(4, user_revision);
66} 66}
67 67
68bool BehaviorInfo::IsAudioRenererProcessingTimeLimit70PercentSupported() const { 68bool BehaviorInfo::IsAudioRendererProcessingTimeLimit70PercentSupported() const {
69 return AudioCommon::IsRevisionSupported(1, user_revision); 69 return AudioCommon::IsRevisionSupported(1, user_revision);
70} 70}
71 71
diff --git a/src/audio_core/behavior_info.h b/src/audio_core/behavior_info.h
index 50948e8df..5a96bf75e 100644
--- a/src/audio_core/behavior_info.h
+++ b/src/audio_core/behavior_info.h
@@ -43,22 +43,22 @@ public:
43 void ClearError(); 43 void ClearError();
44 void UpdateFlags(u64_le dest_flags); 44 void UpdateFlags(u64_le dest_flags);
45 void SetUserRevision(u32_le revision); 45 void SetUserRevision(u32_le revision);
46 u32_le GetUserRevision() const; 46 [[nodiscard]] u32_le GetUserRevision() const;
47 u32_le GetProcessRevision() const; 47 [[nodiscard]] u32_le GetProcessRevision() const;
48 48
49 bool IsAdpcmLoopContextBugFixed() const; 49 [[nodiscard]] bool IsAdpcmLoopContextBugFixed() const;
50 bool IsSplitterSupported() const; 50 [[nodiscard]] bool IsSplitterSupported() const;
51 bool IsLongSizePreDelaySupported() const; 51 [[nodiscard]] bool IsLongSizePreDelaySupported() const;
52 bool IsAudioRenererProcessingTimeLimit80PercentSupported() const; 52 [[nodiscard]] bool IsAudioRendererProcessingTimeLimit80PercentSupported() const;
53 bool IsAudioRenererProcessingTimeLimit75PercentSupported() const; 53 [[nodiscard]] bool IsAudioRendererProcessingTimeLimit75PercentSupported() const;
54 bool IsAudioRenererProcessingTimeLimit70PercentSupported() const; 54 [[nodiscard]] bool IsAudioRendererProcessingTimeLimit70PercentSupported() const;
55 bool IsElapsedFrameCountSupported() const; 55 [[nodiscard]] bool IsElapsedFrameCountSupported() const;
56 bool IsMemoryPoolForceMappingEnabled() const; 56 [[nodiscard]] bool IsMemoryPoolForceMappingEnabled() const;
57 bool IsFlushVoiceWaveBuffersSupported() const; 57 [[nodiscard]] bool IsFlushVoiceWaveBuffersSupported() const;
58 bool IsVoicePlayedSampleCountResetAtLoopPointSupported() const; 58 [[nodiscard]] bool IsVoicePlayedSampleCountResetAtLoopPointSupported() const;
59 bool IsVoicePitchAndSrcSkippedSupported() const; 59 [[nodiscard]] bool IsVoicePitchAndSrcSkippedSupported() const;
60 bool IsMixInParameterDirtyOnlyUpdateSupported() const; 60 [[nodiscard]] bool IsMixInParameterDirtyOnlyUpdateSupported() const;
61 bool IsSplitterBugFixed() const; 61 [[nodiscard]] bool IsSplitterBugFixed() const;
62 void CopyErrorInfo(OutParams& dst); 62 void CopyErrorInfo(OutParams& dst);
63 63
64private: 64private:
diff --git a/src/audio_core/buffer.h b/src/audio_core/buffer.h
index 5ee09e9aa..ccc46ef82 100644
--- a/src/audio_core/buffer.h
+++ b/src/audio_core/buffer.h
@@ -18,7 +18,7 @@ class Buffer {
18public: 18public:
19 using Tag = u64; 19 using Tag = u64;
20 20
21 Buffer(Tag tag, std::vector<s16>&& samples) : tag{tag}, samples{std::move(samples)} {} 21 Buffer(Tag tag_, std::vector<s16>&& samples_) : tag{tag_}, samples{std::move(samples_)} {}
22 22
23 /// Returns the raw audio data for the buffer 23 /// Returns the raw audio data for the buffer
24 std::vector<s16>& GetSamples() { 24 std::vector<s16>& GetSamples() {
diff --git a/src/audio_core/codec.cpp b/src/audio_core/codec.cpp
index c5a0d98ce..2fb91c13a 100644
--- a/src/audio_core/codec.cpp
+++ b/src/audio_core/codec.cpp
@@ -16,8 +16,9 @@ std::vector<s16> DecodeADPCM(const u8* const data, std::size_t size, const ADPCM
16 16
17 constexpr std::size_t FRAME_LEN = 8; 17 constexpr std::size_t FRAME_LEN = 8;
18 constexpr std::size_t SAMPLES_PER_FRAME = 14; 18 constexpr std::size_t SAMPLES_PER_FRAME = 14;
19 constexpr std::array<int, 16> SIGNED_NIBBLES = { 19 static constexpr std::array<int, 16> SIGNED_NIBBLES{
20 {0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1}}; 20 0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1,
21 };
21 22
22 const std::size_t sample_count = (size / FRAME_LEN) * SAMPLES_PER_FRAME; 23 const std::size_t sample_count = (size / FRAME_LEN) * SAMPLES_PER_FRAME;
23 const std::size_t ret_size = 24 const std::size_t ret_size =
diff --git a/src/audio_core/codec.h b/src/audio_core/codec.h
index ef2ce01a8..9507abb1b 100644
--- a/src/audio_core/codec.h
+++ b/src/audio_core/codec.h
@@ -38,7 +38,7 @@ using ADPCM_Coeff = std::array<s16, 16>;
38 * @param state ADPCM state, this is updated with new state 38 * @param state ADPCM state, this is updated with new state
39 * @return Decoded stereo signed PCM16 data, sample_count in length 39 * @return Decoded stereo signed PCM16 data, sample_count in length
40 */ 40 */
41std::vector<s16> DecodeADPCM(const u8* const data, std::size_t size, const ADPCM_Coeff& coeff, 41std::vector<s16> DecodeADPCM(const u8* data, std::size_t size, const ADPCM_Coeff& coeff,
42 ADPCMState& state); 42 ADPCMState& state);
43 43
44}; // namespace AudioCore::Codec 44}; // namespace AudioCore::Codec
diff --git a/src/audio_core/command_generator.cpp b/src/audio_core/command_generator.cpp
index 8f7da49e6..a4a9a757d 100644
--- a/src/audio_core/command_generator.cpp
+++ b/src/audio_core/command_generator.cpp
@@ -67,12 +67,12 @@ s32 ApplyMixDepop(s32* output, s32 first_sample, s32 delta, s32 sample_count) {
67 67
68} // namespace 68} // namespace
69 69
70CommandGenerator::CommandGenerator(AudioCommon::AudioRendererParameter& worker_params, 70CommandGenerator::CommandGenerator(AudioCommon::AudioRendererParameter& worker_params_,
71 VoiceContext& voice_context, MixContext& mix_context, 71 VoiceContext& voice_context_, MixContext& mix_context_,
72 SplitterContext& splitter_context, EffectContext& effect_context, 72 SplitterContext& splitter_context_,
73 Core::Memory::Memory& memory) 73 EffectContext& effect_context_, Core::Memory::Memory& memory_)
74 : worker_params(worker_params), voice_context(voice_context), mix_context(mix_context), 74 : worker_params(worker_params_), voice_context(voice_context_), mix_context(mix_context_),
75 splitter_context(splitter_context), effect_context(effect_context), memory(memory), 75 splitter_context(splitter_context_), effect_context(effect_context_), memory(memory_),
76 mix_buffer((worker_params.mix_buffer_count + AudioCommon::MAX_CHANNEL_COUNT) * 76 mix_buffer((worker_params.mix_buffer_count + AudioCommon::MAX_CHANNEL_COUNT) *
77 worker_params.sample_count), 77 worker_params.sample_count),
78 sample_buffer(MIX_BUFFER_SIZE), 78 sample_buffer(MIX_BUFFER_SIZE),
@@ -152,7 +152,7 @@ void CommandGenerator::GenerateVoiceCommand(ServerVoiceInfo& voice_info) {
152 if (!destination_data->IsConfigured()) { 152 if (!destination_data->IsConfigured()) {
153 continue; 153 continue;
154 } 154 }
155 if (destination_data->GetMixId() >= mix_context.GetCount()) { 155 if (destination_data->GetMixId() >= static_cast<int>(mix_context.GetCount())) {
156 continue; 156 continue;
157 } 157 }
158 158
@@ -255,7 +255,8 @@ void CommandGenerator::GenerateDataSourceCommand(ServerVoiceInfo& voice_info, Vo
255 255
256void CommandGenerator::GenerateBiquadFilterCommandForVoice(ServerVoiceInfo& voice_info, 256void CommandGenerator::GenerateBiquadFilterCommandForVoice(ServerVoiceInfo& voice_info,
257 VoiceState& dsp_state, 257 VoiceState& dsp_state,
258 s32 mix_buffer_count, s32 channel) { 258 [[maybe_unused]] s32 mix_buffer_count,
259 [[maybe_unused]] s32 channel) {
259 for (std::size_t i = 0; i < AudioCommon::MAX_BIQUAD_FILTERS; i++) { 260 for (std::size_t i = 0; i < AudioCommon::MAX_BIQUAD_FILTERS; i++) {
260 const auto& in_params = voice_info.GetInParams(); 261 const auto& in_params = voice_info.GetInParams();
261 auto& biquad_filter = in_params.biquad_filter[i]; 262 auto& biquad_filter = in_params.biquad_filter[i];
@@ -278,9 +279,12 @@ void CommandGenerator::GenerateBiquadFilterCommandForVoice(ServerVoiceInfo& voic
278 } 279 }
279} 280}
280 281
281void AudioCore::CommandGenerator::GenerateBiquadFilterCommand( 282void CommandGenerator::GenerateBiquadFilterCommand([[maybe_unused]] s32 mix_buffer_id,
282 s32 mix_buffer, const BiquadFilterParameter& params, std::array<s64, 2>& state, 283 const BiquadFilterParameter& params,
283 std::size_t input_offset, std::size_t output_offset, s32 sample_count, s32 node_id) { 284 std::array<s64, 2>& state,
285 std::size_t input_offset,
286 std::size_t output_offset, s32 sample_count,
287 s32 node_id) {
284 if (dumping_frame) { 288 if (dumping_frame) {
285 LOG_DEBUG(Audio, 289 LOG_DEBUG(Audio,
286 "(DSP_TRACE) GenerateBiquadFilterCommand node_id={}, " 290 "(DSP_TRACE) GenerateBiquadFilterCommand node_id={}, "
@@ -435,7 +439,7 @@ void CommandGenerator::GenerateAuxCommand(s32 mix_buffer_offset, EffectBase* inf
435 GetMixBuffer(output_index), worker_params.sample_count, offset, write_count); 439 GetMixBuffer(output_index), worker_params.sample_count, offset, write_count);
436 memory.WriteBlock(aux->GetRecvInfo(), &recv_info, sizeof(AuxInfoDSP)); 440 memory.WriteBlock(aux->GetRecvInfo(), &recv_info, sizeof(AuxInfoDSP));
437 441
438 if (samples_read != worker_params.sample_count && 442 if (samples_read != static_cast<int>(worker_params.sample_count) &&
439 samples_read <= params.sample_count) { 443 samples_read <= params.sample_count) {
440 std::memset(GetMixBuffer(output_index), 0, params.sample_count - samples_read); 444 std::memset(GetMixBuffer(output_index), 0, params.sample_count - samples_read);
441 } 445 }
@@ -611,7 +615,8 @@ void CommandGenerator::GenerateMixCommands(ServerMixInfo& mix_info) {
611 const auto& dest_mix = mix_context.GetInfo(destination_data->GetMixId()); 615 const auto& dest_mix = mix_context.GetInfo(destination_data->GetMixId());
612 const auto& dest_in_params = dest_mix.GetInParams(); 616 const auto& dest_in_params = dest_mix.GetInParams();
613 const auto mix_index = (base - 1) % in_params.buffer_count + in_params.buffer_offset; 617 const auto mix_index = (base - 1) % in_params.buffer_count + in_params.buffer_offset;
614 for (std::size_t i = 0; i < dest_in_params.buffer_count; i++) { 618 for (std::size_t i = 0; i < static_cast<std::size_t>(dest_in_params.buffer_count);
619 i++) {
615 const auto mixed_volume = in_params.volume * destination_data->GetMixVolume(i); 620 const auto mixed_volume = in_params.volume * destination_data->GetMixVolume(i);
616 if (mixed_volume != 0.0f) { 621 if (mixed_volume != 0.0f) {
617 GenerateMixCommand(dest_in_params.buffer_offset + i, mix_index, mixed_volume, 622 GenerateMixCommand(dest_in_params.buffer_offset + i, mix_index, mixed_volume,
@@ -704,7 +709,7 @@ s32 CommandGenerator::DecodePcm16(ServerVoiceInfo& voice_info, VoiceState& dsp_s
704 std::vector<s16> buffer(samples_processed * channel_count); 709 std::vector<s16> buffer(samples_processed * channel_count);
705 memory.ReadBlock(buffer_pos, buffer.data(), buffer.size() * sizeof(s16)); 710 memory.ReadBlock(buffer_pos, buffer.data(), buffer.size() * sizeof(s16));
706 711
707 for (std::size_t i = 0; i < samples_processed; i++) { 712 for (std::size_t i = 0; i < static_cast<std::size_t>(samples_processed); i++) {
708 sample_buffer[mix_offset + i] = buffer[i * channel_count + channel]; 713 sample_buffer[mix_offset + i] = buffer[i * channel_count + channel];
709 } 714 }
710 } 715 }
@@ -713,7 +718,8 @@ s32 CommandGenerator::DecodePcm16(ServerVoiceInfo& voice_info, VoiceState& dsp_s
713} 718}
714 719
715s32 CommandGenerator::DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_state, 720s32 CommandGenerator::DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_state,
716 s32 sample_count, s32 channel, std::size_t mix_offset) { 721 s32 sample_count, [[maybe_unused]] s32 channel,
722 std::size_t mix_offset) {
717 const auto& in_params = voice_info.GetInParams(); 723 const auto& in_params = voice_info.GetInParams();
718 const auto& wave_buffer = in_params.wave_buffer[dsp_state.wave_buffer_index]; 724 const auto& wave_buffer = in_params.wave_buffer[dsp_state.wave_buffer_index];
719 if (wave_buffer.buffer_address == 0) { 725 if (wave_buffer.buffer_address == 0) {
@@ -726,8 +732,9 @@ s32 CommandGenerator::DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_s
726 return 0; 732 return 0;
727 } 733 }
728 734
729 constexpr std::array<int, 16> SIGNED_NIBBLES = { 735 static constexpr std::array<int, 16> SIGNED_NIBBLES{
730 {0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1}}; 736 0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1,
737 };
731 738
732 constexpr std::size_t FRAME_LEN = 8; 739 constexpr std::size_t FRAME_LEN = 8;
733 constexpr std::size_t NIBBLES_PER_SAMPLE = 16; 740 constexpr std::size_t NIBBLES_PER_SAMPLE = 16;
@@ -789,9 +796,8 @@ s32 CommandGenerator::DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_s
789 position_in_frame += 2; 796 position_in_frame += 2;
790 797
791 // Decode entire frame 798 // Decode entire frame
792 if (remaining_samples >= SAMPLES_PER_FRAME) { 799 if (remaining_samples >= static_cast<int>(SAMPLES_PER_FRAME)) {
793 for (std::size_t i = 0; i < SAMPLES_PER_FRAME / 2; i++) { 800 for (std::size_t i = 0; i < SAMPLES_PER_FRAME / 2; i++) {
794
795 // Sample 1 801 // Sample 1
796 const s32 s0 = SIGNED_NIBBLES[buffer[buffer_offset] >> 4]; 802 const s32 s0 = SIGNED_NIBBLES[buffer[buffer_offset] >> 4];
797 const s32 s1 = SIGNED_NIBBLES[buffer[buffer_offset++] & 0xf]; 803 const s32 s1 = SIGNED_NIBBLES[buffer[buffer_offset++] & 0xf];
@@ -800,7 +806,7 @@ s32 CommandGenerator::DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_s
800 sample_buffer[cur_mix_offset++] = sample_1; 806 sample_buffer[cur_mix_offset++] = sample_1;
801 sample_buffer[cur_mix_offset++] = sample_2; 807 sample_buffer[cur_mix_offset++] = sample_2;
802 } 808 }
803 remaining_samples -= SAMPLES_PER_FRAME; 809 remaining_samples -= static_cast<int>(SAMPLES_PER_FRAME);
804 position_in_frame += SAMPLES_PER_FRAME; 810 position_in_frame += SAMPLES_PER_FRAME;
805 continue; 811 continue;
806 } 812 }
@@ -866,7 +872,6 @@ void CommandGenerator::DecodeFromWaveBuffers(ServerVoiceInfo& voice_info, s32* o
866 const auto resample_rate = static_cast<s32>( 872 const auto resample_rate = static_cast<s32>(
867 static_cast<float>(in_params.sample_rate) / static_cast<float>(target_sample_rate) * 873 static_cast<float>(in_params.sample_rate) / static_cast<float>(target_sample_rate) *
868 static_cast<float>(static_cast<s32>(in_params.pitch * 32768.0f))); 874 static_cast<float>(static_cast<s32>(in_params.pitch * 32768.0f)));
869 auto* output_base = output;
870 if (dsp_state.fraction + sample_count * resample_rate > 875 if (dsp_state.fraction + sample_count * resample_rate >
871 static_cast<s32>(SCALED_MIX_BUFFER_SIZE - 4ULL)) { 876 static_cast<s32>(SCALED_MIX_BUFFER_SIZE - 4ULL)) {
872 return; 877 return;
diff --git a/src/audio_core/command_generator.h b/src/audio_core/command_generator.h
index 967d24078..b937350b1 100644
--- a/src/audio_core/command_generator.h
+++ b/src/audio_core/command_generator.h
@@ -7,7 +7,6 @@
7#include <array> 7#include <array>
8#include "audio_core/common.h" 8#include "audio_core/common.h"
9#include "audio_core/voice_context.h" 9#include "audio_core/voice_context.h"
10#include "common/common_funcs.h"
11#include "common/common_types.h" 10#include "common/common_types.h"
12 11
13namespace Core::Memory { 12namespace Core::Memory {
@@ -26,10 +25,10 @@ using MixVolumeBuffer = std::array<float, AudioCommon::MAX_MIX_BUFFERS>;
26 25
27class CommandGenerator { 26class CommandGenerator {
28public: 27public:
29 explicit CommandGenerator(AudioCommon::AudioRendererParameter& worker_params, 28 explicit CommandGenerator(AudioCommon::AudioRendererParameter& worker_params_,
30 VoiceContext& voice_context, MixContext& mix_context, 29 VoiceContext& voice_context_, MixContext& mix_context_,
31 SplitterContext& splitter_context, EffectContext& effect_context, 30 SplitterContext& splitter_context_, EffectContext& effect_context_,
32 Core::Memory::Memory& memory); 31 Core::Memory::Memory& memory_);
33 ~CommandGenerator(); 32 ~CommandGenerator();
34 33
35 void ClearMixBuffers(); 34 void ClearMixBuffers();
@@ -40,13 +39,13 @@ public:
40 void PreCommand(); 39 void PreCommand();
41 void PostCommand(); 40 void PostCommand();
42 41
43 s32* GetChannelMixBuffer(s32 channel); 42 [[nodiscard]] s32* GetChannelMixBuffer(s32 channel);
44 const s32* GetChannelMixBuffer(s32 channel) const; 43 [[nodiscard]] const s32* GetChannelMixBuffer(s32 channel) const;
45 s32* GetMixBuffer(std::size_t index); 44 [[nodiscard]] s32* GetMixBuffer(std::size_t index);
46 const s32* GetMixBuffer(std::size_t index) const; 45 [[nodiscard]] const s32* GetMixBuffer(std::size_t index) const;
47 std::size_t GetMixChannelBufferOffset(s32 channel) const; 46 [[nodiscard]] std::size_t GetMixChannelBufferOffset(s32 channel) const;
48 47
49 std::size_t GetTotalMixBufferCount() const; 48 [[nodiscard]] std::size_t GetTotalMixBufferCount() const;
50 49
51private: 50private:
52 void GenerateDataSourceCommand(ServerVoiceInfo& voice_info, VoiceState& dsp_state, s32 channel); 51 void GenerateDataSourceCommand(ServerVoiceInfo& voice_info, VoiceState& dsp_state, s32 channel);
@@ -74,7 +73,7 @@ private:
74 void GenerateI3dl2ReverbEffectCommand(s32 mix_buffer_offset, EffectBase* info, bool enabled); 73 void GenerateI3dl2ReverbEffectCommand(s32 mix_buffer_offset, EffectBase* info, bool enabled);
75 void GenerateBiquadFilterEffectCommand(s32 mix_buffer_offset, EffectBase* info, bool enabled); 74 void GenerateBiquadFilterEffectCommand(s32 mix_buffer_offset, EffectBase* info, bool enabled);
76 void GenerateAuxCommand(s32 mix_buffer_offset, EffectBase* info, bool enabled); 75 void GenerateAuxCommand(s32 mix_buffer_offset, EffectBase* info, bool enabled);
77 ServerSplitterDestinationData* GetDestinationData(s32 splitter_id, s32 index); 76 [[nodiscard]] ServerSplitterDestinationData* GetDestinationData(s32 splitter_id, s32 index);
78 77
79 s32 WriteAuxBuffer(AuxInfoDSP& dsp_info, VAddr send_buffer, u32 max_samples, const s32* data, 78 s32 WriteAuxBuffer(AuxInfoDSP& dsp_info, VAddr send_buffer, u32 max_samples, const s32* data,
80 u32 sample_count, u32 write_offset, u32 write_count); 79 u32 sample_count, u32 write_offset, u32 write_count);
diff --git a/src/audio_core/common.h b/src/audio_core/common.h
index 72ebce221..ec59a3ba9 100644
--- a/src/audio_core/common.h
+++ b/src/audio_core/common.h
@@ -3,6 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
6
6#include "common/common_funcs.h" 7#include "common/common_funcs.h"
7#include "common/common_types.h" 8#include "common/common_types.h"
8#include "common/swap.h" 9#include "common/swap.h"
@@ -21,7 +22,7 @@ constexpr std::size_t MAX_CHANNEL_COUNT = 6;
21constexpr std::size_t MAX_WAVE_BUFFERS = 4; 22constexpr std::size_t MAX_WAVE_BUFFERS = 4;
22constexpr std::size_t MAX_SAMPLE_HISTORY = 4; 23constexpr std::size_t MAX_SAMPLE_HISTORY = 4;
23constexpr u32 STREAM_SAMPLE_RATE = 48000; 24constexpr u32 STREAM_SAMPLE_RATE = 48000;
24constexpr u32 STREAM_NUM_CHANNELS = 6; 25constexpr u32 STREAM_NUM_CHANNELS = 2;
25constexpr s32 NO_SPLITTER = -1; 26constexpr s32 NO_SPLITTER = -1;
26constexpr s32 NO_MIX = 0x7fffffff; 27constexpr s32 NO_MIX = 0x7fffffff;
27constexpr s32 NO_FINAL_MIX = std::numeric_limits<s32>::min(); 28constexpr s32 NO_FINAL_MIX = std::numeric_limits<s32>::min();
diff --git a/src/audio_core/cubeb_sink.cpp b/src/audio_core/cubeb_sink.cpp
index 83c06c0ed..043447eaa 100644
--- a/src/audio_core/cubeb_sink.cpp
+++ b/src/audio_core/cubeb_sink.cpp
@@ -21,15 +21,16 @@ namespace AudioCore {
21 21
22class CubebSinkStream final : public SinkStream { 22class CubebSinkStream final : public SinkStream {
23public: 23public:
24 CubebSinkStream(cubeb* ctx, u32 sample_rate, u32 num_channels_, cubeb_devid output_device, 24 CubebSinkStream(cubeb* ctx_, u32 sample_rate, u32 num_channels_, cubeb_devid output_device,
25 const std::string& name) 25 const std::string& name)
26 : ctx{ctx}, num_channels{std::min(num_channels_, 6u)}, time_stretch{sample_rate, 26 : ctx{ctx_}, num_channels{std::min(num_channels_, 6u)}, time_stretch{sample_rate,
27 num_channels} { 27 num_channels} {
28 28
29 cubeb_stream_params params{}; 29 cubeb_stream_params params{};
30 params.rate = sample_rate; 30 params.rate = sample_rate;
31 params.channels = num_channels; 31 params.channels = num_channels;
32 params.format = CUBEB_SAMPLE_S16NE; 32 params.format = CUBEB_SAMPLE_S16NE;
33 params.prefs = CUBEB_STREAM_PREF_PERSIST;
33 switch (num_channels) { 34 switch (num_channels) {
34 case 1: 35 case 1:
35 params.layout = CUBEB_LAYOUT_MONO; 36 params.layout = CUBEB_LAYOUT_MONO;
@@ -93,8 +94,10 @@ public:
93 constexpr s32 clev{707}; // center mixing level coefficient 94 constexpr s32 clev{707}; // center mixing level coefficient
94 constexpr s32 slev{707}; // surround mixing level coefficient 95 constexpr s32 slev{707}; // surround mixing level coefficient
95 96
96 buf.push_back(left + (clev * center / 1000) + (slev * surround_left / 1000)); 97 buf.push_back(static_cast<s16>(left + (clev * center / 1000) +
97 buf.push_back(right + (clev * center / 1000) + (slev * surround_right / 1000)); 98 (slev * surround_left / 1000)));
99 buf.push_back(static_cast<s16>(right + (clev * center / 1000) +
100 (slev * surround_right / 1000)));
98 } 101 }
99 queue.Push(buf); 102 queue.Push(buf);
100 return; 103 return;
@@ -190,10 +193,11 @@ SinkStream& CubebSink::AcquireSinkStream(u32 sample_rate, u32 num_channels,
190 return *sink_streams.back(); 193 return *sink_streams.back();
191} 194}
192 195
193long CubebSinkStream::DataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer, 196long CubebSinkStream::DataCallback([[maybe_unused]] cubeb_stream* stream, void* user_data,
194 void* output_buffer, long num_frames) { 197 [[maybe_unused]] const void* input_buffer, void* output_buffer,
195 CubebSinkStream* impl = static_cast<CubebSinkStream*>(user_data); 198 long num_frames) {
196 u8* buffer = reinterpret_cast<u8*>(output_buffer); 199 auto* impl = static_cast<CubebSinkStream*>(user_data);
200 auto* buffer = static_cast<u8*>(output_buffer);
197 201
198 if (!impl) { 202 if (!impl) {
199 return {}; 203 return {};
@@ -234,7 +238,9 @@ long CubebSinkStream::DataCallback(cubeb_stream* stream, void* user_data, const
234 return num_frames; 238 return num_frames;
235} 239}
236 240
237void CubebSinkStream::StateCallback(cubeb_stream* stream, void* user_data, cubeb_state state) {} 241void CubebSinkStream::StateCallback([[maybe_unused]] cubeb_stream* stream,
242 [[maybe_unused]] void* user_data,
243 [[maybe_unused]] cubeb_state state) {}
238 244
239std::vector<std::string> ListCubebSinkDevices() { 245std::vector<std::string> ListCubebSinkDevices() {
240 std::vector<std::string> device_list; 246 std::vector<std::string> device_list;
diff --git a/src/audio_core/effect_context.cpp b/src/audio_core/effect_context.cpp
index adfec3df5..f770b9608 100644
--- a/src/audio_core/effect_context.cpp
+++ b/src/audio_core/effect_context.cpp
@@ -12,7 +12,7 @@ bool ValidChannelCountForEffect(s32 channel_count) {
12} 12}
13} // namespace 13} // namespace
14 14
15EffectContext::EffectContext(std::size_t effect_count) : effect_count(effect_count) { 15EffectContext::EffectContext(std::size_t effect_count_) : effect_count(effect_count_) {
16 effects.reserve(effect_count); 16 effects.reserve(effect_count);
17 std::generate_n(std::back_inserter(effects), effect_count, 17 std::generate_n(std::back_inserter(effects), effect_count,
18 [] { return std::make_unique<EffectStubbed>(); }); 18 [] { return std::make_unique<EffectStubbed>(); });
@@ -61,13 +61,13 @@ const EffectBase* EffectContext::GetInfo(std::size_t i) const {
61 return effects.at(i).get(); 61 return effects.at(i).get();
62} 62}
63 63
64EffectStubbed::EffectStubbed() : EffectBase::EffectBase(EffectType::Invalid) {} 64EffectStubbed::EffectStubbed() : EffectBase(EffectType::Invalid) {}
65EffectStubbed::~EffectStubbed() = default; 65EffectStubbed::~EffectStubbed() = default;
66 66
67void EffectStubbed::Update(EffectInfo::InParams& in_params) {} 67void EffectStubbed::Update([[maybe_unused]] EffectInfo::InParams& in_params) {}
68void EffectStubbed::UpdateForCommandGeneration() {} 68void EffectStubbed::UpdateForCommandGeneration() {}
69 69
70EffectBase::EffectBase(EffectType effect_type) : effect_type(effect_type) {} 70EffectBase::EffectBase(EffectType effect_type_) : effect_type(effect_type_) {}
71EffectBase::~EffectBase() = default; 71EffectBase::~EffectBase() = default;
72 72
73UsageState EffectBase::GetUsage() const { 73UsageState EffectBase::GetUsage() const {
@@ -90,32 +90,32 @@ s32 EffectBase::GetProcessingOrder() const {
90 return processing_order; 90 return processing_order;
91} 91}
92 92
93EffectI3dl2Reverb::EffectI3dl2Reverb() : EffectGeneric::EffectGeneric(EffectType::I3dl2Reverb) {} 93EffectI3dl2Reverb::EffectI3dl2Reverb() : EffectGeneric(EffectType::I3dl2Reverb) {}
94EffectI3dl2Reverb::~EffectI3dl2Reverb() = default; 94EffectI3dl2Reverb::~EffectI3dl2Reverb() = default;
95 95
96void EffectI3dl2Reverb::Update(EffectInfo::InParams& in_params) { 96void EffectI3dl2Reverb::Update(EffectInfo::InParams& in_params) {
97 auto& internal_params = GetParams(); 97 auto& params = GetParams();
98 const auto* reverb_params = reinterpret_cast<I3dl2ReverbParams*>(in_params.raw.data()); 98 const auto* reverb_params = reinterpret_cast<I3dl2ReverbParams*>(in_params.raw.data());
99 if (!ValidChannelCountForEffect(reverb_params->max_channels)) { 99 if (!ValidChannelCountForEffect(reverb_params->max_channels)) {
100 UNREACHABLE_MSG("Invalid reverb max channel count {}", reverb_params->max_channels); 100 UNREACHABLE_MSG("Invalid reverb max channel count {}", reverb_params->max_channels);
101 return; 101 return;
102 } 102 }
103 103
104 const auto last_status = internal_params.status; 104 const auto last_status = params.status;
105 mix_id = in_params.mix_id; 105 mix_id = in_params.mix_id;
106 processing_order = in_params.processing_order; 106 processing_order = in_params.processing_order;
107 internal_params = *reverb_params; 107 params = *reverb_params;
108 if (!ValidChannelCountForEffect(reverb_params->channel_count)) { 108 if (!ValidChannelCountForEffect(reverb_params->channel_count)) {
109 internal_params.channel_count = internal_params.max_channels; 109 params.channel_count = params.max_channels;
110 } 110 }
111 enabled = in_params.is_enabled; 111 enabled = in_params.is_enabled;
112 if (last_status != ParameterStatus::Updated) { 112 if (last_status != ParameterStatus::Updated) {
113 internal_params.status = last_status; 113 params.status = last_status;
114 } 114 }
115 115
116 if (in_params.is_new || skipped) { 116 if (in_params.is_new || skipped) {
117 usage = UsageState::Initialized; 117 usage = UsageState::Initialized;
118 internal_params.status = ParameterStatus::Initialized; 118 params.status = ParameterStatus::Initialized;
119 skipped = in_params.buffer_address == 0 || in_params.buffer_size == 0; 119 skipped = in_params.buffer_address == 0 || in_params.buffer_size == 0;
120 } 120 }
121} 121}
@@ -129,15 +129,15 @@ void EffectI3dl2Reverb::UpdateForCommandGeneration() {
129 GetParams().status = ParameterStatus::Updated; 129 GetParams().status = ParameterStatus::Updated;
130} 130}
131 131
132EffectBiquadFilter::EffectBiquadFilter() : EffectGeneric::EffectGeneric(EffectType::BiquadFilter) {} 132EffectBiquadFilter::EffectBiquadFilter() : EffectGeneric(EffectType::BiquadFilter) {}
133EffectBiquadFilter::~EffectBiquadFilter() = default; 133EffectBiquadFilter::~EffectBiquadFilter() = default;
134 134
135void EffectBiquadFilter::Update(EffectInfo::InParams& in_params) { 135void EffectBiquadFilter::Update(EffectInfo::InParams& in_params) {
136 auto& internal_params = GetParams(); 136 auto& params = GetParams();
137 const auto* biquad_params = reinterpret_cast<BiquadFilterParams*>(in_params.raw.data()); 137 const auto* biquad_params = reinterpret_cast<BiquadFilterParams*>(in_params.raw.data());
138 mix_id = in_params.mix_id; 138 mix_id = in_params.mix_id;
139 processing_order = in_params.processing_order; 139 processing_order = in_params.processing_order;
140 internal_params = *biquad_params; 140 params = *biquad_params;
141 enabled = in_params.is_enabled; 141 enabled = in_params.is_enabled;
142} 142}
143 143
@@ -150,7 +150,7 @@ void EffectBiquadFilter::UpdateForCommandGeneration() {
150 GetParams().status = ParameterStatus::Updated; 150 GetParams().status = ParameterStatus::Updated;
151} 151}
152 152
153EffectAuxInfo::EffectAuxInfo() : EffectGeneric::EffectGeneric(EffectType::Aux) {} 153EffectAuxInfo::EffectAuxInfo() : EffectGeneric(EffectType::Aux) {}
154EffectAuxInfo::~EffectAuxInfo() = default; 154EffectAuxInfo::~EffectAuxInfo() = default;
155 155
156void EffectAuxInfo::Update(EffectInfo::InParams& in_params) { 156void EffectAuxInfo::Update(EffectInfo::InParams& in_params) {
@@ -184,48 +184,48 @@ void EffectAuxInfo::UpdateForCommandGeneration() {
184 } 184 }
185} 185}
186 186
187const VAddr EffectAuxInfo::GetSendInfo() const { 187VAddr EffectAuxInfo::GetSendInfo() const {
188 return send_info; 188 return send_info;
189} 189}
190 190
191const VAddr EffectAuxInfo::GetSendBuffer() const { 191VAddr EffectAuxInfo::GetSendBuffer() const {
192 return send_buffer; 192 return send_buffer;
193} 193}
194 194
195const VAddr EffectAuxInfo::GetRecvInfo() const { 195VAddr EffectAuxInfo::GetRecvInfo() const {
196 return recv_info; 196 return recv_info;
197} 197}
198 198
199const VAddr EffectAuxInfo::GetRecvBuffer() const { 199VAddr EffectAuxInfo::GetRecvBuffer() const {
200 return recv_buffer; 200 return recv_buffer;
201} 201}
202 202
203EffectDelay::EffectDelay() : EffectGeneric::EffectGeneric(EffectType::Delay) {} 203EffectDelay::EffectDelay() : EffectGeneric(EffectType::Delay) {}
204EffectDelay::~EffectDelay() = default; 204EffectDelay::~EffectDelay() = default;
205 205
206void EffectDelay::Update(EffectInfo::InParams& in_params) { 206void EffectDelay::Update(EffectInfo::InParams& in_params) {
207 const auto* delay_params = reinterpret_cast<DelayParams*>(in_params.raw.data()); 207 const auto* delay_params = reinterpret_cast<DelayParams*>(in_params.raw.data());
208 auto& internal_params = GetParams(); 208 auto& params = GetParams();
209 if (!ValidChannelCountForEffect(delay_params->max_channels)) { 209 if (!ValidChannelCountForEffect(delay_params->max_channels)) {
210 return; 210 return;
211 } 211 }
212 212
213 const auto last_status = internal_params.status; 213 const auto last_status = params.status;
214 mix_id = in_params.mix_id; 214 mix_id = in_params.mix_id;
215 processing_order = in_params.processing_order; 215 processing_order = in_params.processing_order;
216 internal_params = *delay_params; 216 params = *delay_params;
217 if (!ValidChannelCountForEffect(delay_params->channels)) { 217 if (!ValidChannelCountForEffect(delay_params->channels)) {
218 internal_params.channels = internal_params.max_channels; 218 params.channels = params.max_channels;
219 } 219 }
220 enabled = in_params.is_enabled; 220 enabled = in_params.is_enabled;
221 221
222 if (last_status != ParameterStatus::Updated) { 222 if (last_status != ParameterStatus::Updated) {
223 internal_params.status = last_status; 223 params.status = last_status;
224 } 224 }
225 225
226 if (in_params.is_new || skipped) { 226 if (in_params.is_new || skipped) {
227 usage = UsageState::Initialized; 227 usage = UsageState::Initialized;
228 internal_params.status = ParameterStatus::Initialized; 228 params.status = ParameterStatus::Initialized;
229 skipped = in_params.buffer_address == 0 || in_params.buffer_size == 0; 229 skipped = in_params.buffer_address == 0 || in_params.buffer_size == 0;
230 } 230 }
231} 231}
@@ -239,7 +239,7 @@ void EffectDelay::UpdateForCommandGeneration() {
239 GetParams().status = ParameterStatus::Updated; 239 GetParams().status = ParameterStatus::Updated;
240} 240}
241 241
242EffectBufferMixer::EffectBufferMixer() : EffectGeneric::EffectGeneric(EffectType::BufferMixer) {} 242EffectBufferMixer::EffectBufferMixer() : EffectGeneric(EffectType::BufferMixer) {}
243EffectBufferMixer::~EffectBufferMixer() = default; 243EffectBufferMixer::~EffectBufferMixer() = default;
244 244
245void EffectBufferMixer::Update(EffectInfo::InParams& in_params) { 245void EffectBufferMixer::Update(EffectInfo::InParams& in_params) {
@@ -257,32 +257,32 @@ void EffectBufferMixer::UpdateForCommandGeneration() {
257 } 257 }
258} 258}
259 259
260EffectReverb::EffectReverb() : EffectGeneric::EffectGeneric(EffectType::Reverb) {} 260EffectReverb::EffectReverb() : EffectGeneric(EffectType::Reverb) {}
261EffectReverb::~EffectReverb() = default; 261EffectReverb::~EffectReverb() = default;
262 262
263void EffectReverb::Update(EffectInfo::InParams& in_params) { 263void EffectReverb::Update(EffectInfo::InParams& in_params) {
264 const auto* reverb_params = reinterpret_cast<ReverbParams*>(in_params.raw.data()); 264 const auto* reverb_params = reinterpret_cast<ReverbParams*>(in_params.raw.data());
265 auto& internal_params = GetParams(); 265 auto& params = GetParams();
266 if (!ValidChannelCountForEffect(reverb_params->max_channels)) { 266 if (!ValidChannelCountForEffect(reverb_params->max_channels)) {
267 return; 267 return;
268 } 268 }
269 269
270 const auto last_status = internal_params.status; 270 const auto last_status = params.status;
271 mix_id = in_params.mix_id; 271 mix_id = in_params.mix_id;
272 processing_order = in_params.processing_order; 272 processing_order = in_params.processing_order;
273 internal_params = *reverb_params; 273 params = *reverb_params;
274 if (!ValidChannelCountForEffect(reverb_params->channels)) { 274 if (!ValidChannelCountForEffect(reverb_params->channels)) {
275 internal_params.channels = internal_params.max_channels; 275 params.channels = params.max_channels;
276 } 276 }
277 enabled = in_params.is_enabled; 277 enabled = in_params.is_enabled;
278 278
279 if (last_status != ParameterStatus::Updated) { 279 if (last_status != ParameterStatus::Updated) {
280 internal_params.status = last_status; 280 params.status = last_status;
281 } 281 }
282 282
283 if (in_params.is_new || skipped) { 283 if (in_params.is_new || skipped) {
284 usage = UsageState::Initialized; 284 usage = UsageState::Initialized;
285 internal_params.status = ParameterStatus::Initialized; 285 params.status = ParameterStatus::Initialized;
286 skipped = in_params.buffer_address == 0 || in_params.buffer_size == 0; 286 skipped = in_params.buffer_address == 0 || in_params.buffer_size == 0;
287 } 287 }
288} 288}
diff --git a/src/audio_core/effect_context.h b/src/audio_core/effect_context.h
index 2f2da72dd..c5e0b398c 100644
--- a/src/audio_core/effect_context.h
+++ b/src/audio_core/effect_context.h
@@ -166,13 +166,13 @@ public:
166 std::array<u8, 0xa0> raw; 166 std::array<u8, 0xa0> raw;
167 }; 167 };
168 }; 168 };
169 static_assert(sizeof(EffectInfo::InParams) == 0xc0, "InParams is an invalid size"); 169 static_assert(sizeof(InParams) == 0xc0, "InParams is an invalid size");
170 170
171 struct OutParams { 171 struct OutParams {
172 UsageStatus status{}; 172 UsageStatus status{};
173 INSERT_PADDING_BYTES(15); 173 INSERT_PADDING_BYTES(15);
174 }; 174 };
175 static_assert(sizeof(EffectInfo::OutParams) == 0x10, "OutParams is an invalid size"); 175 static_assert(sizeof(OutParams) == 0x10, "OutParams is an invalid size");
176}; 176};
177 177
178struct AuxAddress { 178struct AuxAddress {
@@ -184,16 +184,16 @@ struct AuxAddress {
184 184
185class EffectBase { 185class EffectBase {
186public: 186public:
187 EffectBase(EffectType effect_type); 187 explicit EffectBase(EffectType effect_type_);
188 ~EffectBase(); 188 virtual ~EffectBase();
189 189
190 virtual void Update(EffectInfo::InParams& in_params) = 0; 190 virtual void Update(EffectInfo::InParams& in_params) = 0;
191 virtual void UpdateForCommandGeneration() = 0; 191 virtual void UpdateForCommandGeneration() = 0;
192 UsageState GetUsage() const; 192 [[nodiscard]] UsageState GetUsage() const;
193 EffectType GetType() const; 193 [[nodiscard]] EffectType GetType() const;
194 bool IsEnabled() const; 194 [[nodiscard]] bool IsEnabled() const;
195 s32 GetMixID() const; 195 [[nodiscard]] s32 GetMixID() const;
196 s32 GetProcessingOrder() const; 196 [[nodiscard]] s32 GetProcessingOrder() const;
197 197
198protected: 198protected:
199 UsageState usage{UsageState::Invalid}; 199 UsageState usage{UsageState::Invalid};
@@ -206,8 +206,7 @@ protected:
206template <typename T> 206template <typename T>
207class EffectGeneric : public EffectBase { 207class EffectGeneric : public EffectBase {
208public: 208public:
209 EffectGeneric(EffectType effect_type) : EffectBase::EffectBase(effect_type) {} 209 explicit EffectGeneric(EffectType effect_type_) : EffectBase(effect_type_) {}
210 ~EffectGeneric() = default;
211 210
212 T& GetParams() { 211 T& GetParams() {
213 return internal_params; 212 return internal_params;
@@ -224,7 +223,7 @@ private:
224class EffectStubbed : public EffectBase { 223class EffectStubbed : public EffectBase {
225public: 224public:
226 explicit EffectStubbed(); 225 explicit EffectStubbed();
227 ~EffectStubbed(); 226 ~EffectStubbed() override;
228 227
229 void Update(EffectInfo::InParams& in_params) override; 228 void Update(EffectInfo::InParams& in_params) override;
230 void UpdateForCommandGeneration() override; 229 void UpdateForCommandGeneration() override;
@@ -233,7 +232,7 @@ public:
233class EffectI3dl2Reverb : public EffectGeneric<I3dl2ReverbParams> { 232class EffectI3dl2Reverb : public EffectGeneric<I3dl2ReverbParams> {
234public: 233public:
235 explicit EffectI3dl2Reverb(); 234 explicit EffectI3dl2Reverb();
236 ~EffectI3dl2Reverb(); 235 ~EffectI3dl2Reverb() override;
237 236
238 void Update(EffectInfo::InParams& in_params) override; 237 void Update(EffectInfo::InParams& in_params) override;
239 void UpdateForCommandGeneration() override; 238 void UpdateForCommandGeneration() override;
@@ -245,7 +244,7 @@ private:
245class EffectBiquadFilter : public EffectGeneric<BiquadFilterParams> { 244class EffectBiquadFilter : public EffectGeneric<BiquadFilterParams> {
246public: 245public:
247 explicit EffectBiquadFilter(); 246 explicit EffectBiquadFilter();
248 ~EffectBiquadFilter(); 247 ~EffectBiquadFilter() override;
249 248
250 void Update(EffectInfo::InParams& in_params) override; 249 void Update(EffectInfo::InParams& in_params) override;
251 void UpdateForCommandGeneration() override; 250 void UpdateForCommandGeneration() override;
@@ -254,14 +253,14 @@ public:
254class EffectAuxInfo : public EffectGeneric<AuxInfo> { 253class EffectAuxInfo : public EffectGeneric<AuxInfo> {
255public: 254public:
256 explicit EffectAuxInfo(); 255 explicit EffectAuxInfo();
257 ~EffectAuxInfo(); 256 ~EffectAuxInfo() override;
258 257
259 void Update(EffectInfo::InParams& in_params) override; 258 void Update(EffectInfo::InParams& in_params) override;
260 void UpdateForCommandGeneration() override; 259 void UpdateForCommandGeneration() override;
261 const VAddr GetSendInfo() const; 260 [[nodiscard]] VAddr GetSendInfo() const;
262 const VAddr GetSendBuffer() const; 261 [[nodiscard]] VAddr GetSendBuffer() const;
263 const VAddr GetRecvInfo() const; 262 [[nodiscard]] VAddr GetRecvInfo() const;
264 const VAddr GetRecvBuffer() const; 263 [[nodiscard]] VAddr GetRecvBuffer() const;
265 264
266private: 265private:
267 VAddr send_info{}; 266 VAddr send_info{};
@@ -275,7 +274,7 @@ private:
275class EffectDelay : public EffectGeneric<DelayParams> { 274class EffectDelay : public EffectGeneric<DelayParams> {
276public: 275public:
277 explicit EffectDelay(); 276 explicit EffectDelay();
278 ~EffectDelay(); 277 ~EffectDelay() override;
279 278
280 void Update(EffectInfo::InParams& in_params) override; 279 void Update(EffectInfo::InParams& in_params) override;
281 void UpdateForCommandGeneration() override; 280 void UpdateForCommandGeneration() override;
@@ -287,7 +286,7 @@ private:
287class EffectBufferMixer : public EffectGeneric<BufferMixerParams> { 286class EffectBufferMixer : public EffectGeneric<BufferMixerParams> {
288public: 287public:
289 explicit EffectBufferMixer(); 288 explicit EffectBufferMixer();
290 ~EffectBufferMixer(); 289 ~EffectBufferMixer() override;
291 290
292 void Update(EffectInfo::InParams& in_params) override; 291 void Update(EffectInfo::InParams& in_params) override;
293 void UpdateForCommandGeneration() override; 292 void UpdateForCommandGeneration() override;
@@ -296,7 +295,7 @@ public:
296class EffectReverb : public EffectGeneric<ReverbParams> { 295class EffectReverb : public EffectGeneric<ReverbParams> {
297public: 296public:
298 explicit EffectReverb(); 297 explicit EffectReverb();
299 ~EffectReverb(); 298 ~EffectReverb() override;
300 299
301 void Update(EffectInfo::InParams& in_params) override; 300 void Update(EffectInfo::InParams& in_params) override;
302 void UpdateForCommandGeneration() override; 301 void UpdateForCommandGeneration() override;
@@ -307,13 +306,13 @@ private:
307 306
308class EffectContext { 307class EffectContext {
309public: 308public:
310 explicit EffectContext(std::size_t effect_count); 309 explicit EffectContext(std::size_t effect_count_);
311 ~EffectContext(); 310 ~EffectContext();
312 311
313 std::size_t GetCount() const; 312 [[nodiscard]] std::size_t GetCount() const;
314 EffectBase* GetInfo(std::size_t i); 313 [[nodiscard]] EffectBase* GetInfo(std::size_t i);
315 EffectBase* RetargetEffect(std::size_t i, EffectType effect); 314 [[nodiscard]] EffectBase* RetargetEffect(std::size_t i, EffectType effect);
316 const EffectBase* GetInfo(std::size_t i) const; 315 [[nodiscard]] const EffectBase* GetInfo(std::size_t i) const;
317 316
318private: 317private:
319 std::size_t effect_count{}; 318 std::size_t effect_count{};
diff --git a/src/audio_core/info_updater.cpp b/src/audio_core/info_updater.cpp
index f53ce21a5..d3ac90827 100644
--- a/src/audio_core/info_updater.cpp
+++ b/src/audio_core/info_updater.cpp
@@ -14,9 +14,9 @@
14 14
15namespace AudioCore { 15namespace AudioCore {
16 16
17InfoUpdater::InfoUpdater(const std::vector<u8>& in_params, std::vector<u8>& out_params, 17InfoUpdater::InfoUpdater(const std::vector<u8>& in_params_, std::vector<u8>& out_params_,
18 BehaviorInfo& behavior_info) 18 BehaviorInfo& behavior_info_)
19 : in_params(in_params), out_params(out_params), behavior_info(behavior_info) { 19 : in_params(in_params_), out_params(out_params_), behavior_info(behavior_info_) {
20 ASSERT( 20 ASSERT(
21 AudioCommon::CanConsumeBuffer(in_params.size(), 0, sizeof(AudioCommon::UpdateDataHeader))); 21 AudioCommon::CanConsumeBuffer(in_params.size(), 0, sizeof(AudioCommon::UpdateDataHeader)));
22 std::memcpy(&input_header, in_params.data(), sizeof(AudioCommon::UpdateDataHeader)); 22 std::memcpy(&input_header, in_params.data(), sizeof(AudioCommon::UpdateDataHeader));
@@ -64,7 +64,6 @@ bool InfoUpdater::UpdateBehaviorInfo(BehaviorInfo& in_behavior_info) {
64} 64}
65 65
66bool InfoUpdater::UpdateMemoryPools(std::vector<ServerMemoryPoolInfo>& memory_pool_info) { 66bool InfoUpdater::UpdateMemoryPools(std::vector<ServerMemoryPoolInfo>& memory_pool_info) {
67 const auto force_mapping = behavior_info.IsMemoryPoolForceMappingEnabled();
68 const auto memory_pool_count = memory_pool_info.size(); 67 const auto memory_pool_count = memory_pool_info.size();
69 const auto total_memory_pool_in = sizeof(ServerMemoryPoolInfo::InParams) * memory_pool_count; 68 const auto total_memory_pool_in = sizeof(ServerMemoryPoolInfo::InParams) * memory_pool_count;
70 const auto total_memory_pool_out = sizeof(ServerMemoryPoolInfo::OutParams) * memory_pool_count; 69 const auto total_memory_pool_out = sizeof(ServerMemoryPoolInfo::OutParams) * memory_pool_count;
@@ -136,8 +135,8 @@ bool InfoUpdater::UpdateVoiceChannelResources(VoiceContext& voice_context) {
136} 135}
137 136
138bool InfoUpdater::UpdateVoices(VoiceContext& voice_context, 137bool InfoUpdater::UpdateVoices(VoiceContext& voice_context,
139 std::vector<ServerMemoryPoolInfo>& memory_pool_info, 138 [[maybe_unused]] std::vector<ServerMemoryPoolInfo>& memory_pool_info,
140 VAddr audio_codec_dsp_addr) { 139 [[maybe_unused]] VAddr audio_codec_dsp_addr) {
141 const auto voice_count = voice_context.GetVoiceCount(); 140 const auto voice_count = voice_context.GetVoiceCount();
142 std::vector<VoiceInfo::InParams> voice_in(voice_count); 141 std::vector<VoiceInfo::InParams> voice_in(voice_count);
143 std::vector<VoiceInfo::OutParams> voice_out(voice_count); 142 std::vector<VoiceInfo::OutParams> voice_out(voice_count);
@@ -166,28 +165,28 @@ bool InfoUpdater::UpdateVoices(VoiceContext& voice_context,
166 165
167 // Update our voices 166 // Update our voices
168 for (std::size_t i = 0; i < voice_count; i++) { 167 for (std::size_t i = 0; i < voice_count; i++) {
169 auto& in_params = voice_in[i]; 168 auto& voice_in_params = voice_in[i];
170 const auto channel_count = static_cast<std::size_t>(in_params.channel_count); 169 const auto channel_count = static_cast<std::size_t>(voice_in_params.channel_count);
171 // Skip if it's not currently in use 170 // Skip if it's not currently in use
172 if (!in_params.is_in_use) { 171 if (!voice_in_params.is_in_use) {
173 continue; 172 continue;
174 } 173 }
175 // Voice states for each channel 174 // Voice states for each channel
176 std::array<VoiceState*, AudioCommon::MAX_CHANNEL_COUNT> voice_states{}; 175 std::array<VoiceState*, AudioCommon::MAX_CHANNEL_COUNT> voice_states{};
177 ASSERT(in_params.id < voice_count); 176 ASSERT(static_cast<std::size_t>(voice_in_params.id) < voice_count);
178 177
179 // Grab our current voice info 178 // Grab our current voice info
180 auto& voice_info = voice_context.GetInfo(static_cast<std::size_t>(in_params.id)); 179 auto& voice_info = voice_context.GetInfo(static_cast<std::size_t>(voice_in_params.id));
181 180
182 ASSERT(channel_count <= AudioCommon::MAX_CHANNEL_COUNT); 181 ASSERT(channel_count <= AudioCommon::MAX_CHANNEL_COUNT);
183 182
184 // Get all our channel voice states 183 // Get all our channel voice states
185 for (std::size_t channel = 0; channel < channel_count; channel++) { 184 for (std::size_t channel = 0; channel < channel_count; channel++) {
186 voice_states[channel] = 185 voice_states[channel] =
187 &voice_context.GetState(in_params.voice_channel_resource_ids[channel]); 186 &voice_context.GetState(voice_in_params.voice_channel_resource_ids[channel]);
188 } 187 }
189 188
190 if (in_params.is_new) { 189 if (voice_in_params.is_new) {
191 // Default our values for our voice 190 // Default our values for our voice
192 voice_info.Initialize(); 191 voice_info.Initialize();
193 if (channel_count == 0 || channel_count > AudioCommon::MAX_CHANNEL_COUNT) { 192 if (channel_count == 0 || channel_count > AudioCommon::MAX_CHANNEL_COUNT) {
@@ -201,12 +200,12 @@ bool InfoUpdater::UpdateVoices(VoiceContext& voice_context,
201 } 200 }
202 201
203 // Update our voice 202 // Update our voice
204 voice_info.UpdateParameters(in_params, behavior_info); 203 voice_info.UpdateParameters(voice_in_params, behavior_info);
205 // TODO(ogniK): Handle mapping errors with behavior info based on in params response 204 // TODO(ogniK): Handle mapping errors with behavior info based on in params response
206 205
207 // Update our wave buffers 206 // Update our wave buffers
208 voice_info.UpdateWaveBuffers(in_params, voice_states, behavior_info); 207 voice_info.UpdateWaveBuffers(voice_in_params, voice_states, behavior_info);
209 voice_info.WriteOutStatus(voice_out[i], in_params, voice_states); 208 voice_info.WriteOutStatus(voice_out[i], voice_in_params, voice_states);
210 } 209 }
211 210
212 if (!AudioCommon::CanConsumeBuffer(out_params.size(), output_offset, voice_out_size)) { 211 if (!AudioCommon::CanConsumeBuffer(out_params.size(), output_offset, voice_out_size)) {
@@ -352,8 +351,8 @@ ResultCode InfoUpdater::UpdateMixes(MixContext& mix_context, std::size_t mix_buf
352 for (std::size_t i = 0; i < mix_count; i++) { 351 for (std::size_t i = 0; i < mix_count; i++) {
353 const auto& in = mix_in_params[i]; 352 const auto& in = mix_in_params[i];
354 total_buffer_count += in.buffer_count; 353 total_buffer_count += in.buffer_count;
355 if (in.dest_mix_id > mix_count && in.dest_mix_id != AudioCommon::NO_MIX && 354 if (static_cast<std::size_t>(in.dest_mix_id) > mix_count &&
356 in.mix_id != AudioCommon::FINAL_MIX) { 355 in.dest_mix_id != AudioCommon::NO_MIX && in.mix_id != AudioCommon::FINAL_MIX) {
357 LOG_ERROR( 356 LOG_ERROR(
358 Audio, 357 Audio,
359 "Invalid mix destination, mix_id={:X}, dest_mix_id={:X}, mix_buffer_count={:X}", 358 "Invalid mix destination, mix_id={:X}, dest_mix_id={:X}, mix_buffer_count={:X}",
@@ -446,7 +445,7 @@ bool InfoUpdater::UpdatePerformanceBuffer() {
446 return true; 445 return true;
447} 446}
448 447
449bool InfoUpdater::UpdateErrorInfo(BehaviorInfo& in_behavior_info) { 448bool InfoUpdater::UpdateErrorInfo([[maybe_unused]] BehaviorInfo& in_behavior_info) {
450 const auto total_beahvior_info_out = sizeof(BehaviorInfo::OutParams); 449 const auto total_beahvior_info_out = sizeof(BehaviorInfo::OutParams);
451 450
452 if (!AudioCommon::CanConsumeBuffer(out_params.size(), output_offset, total_beahvior_info_out)) { 451 if (!AudioCommon::CanConsumeBuffer(out_params.size(), output_offset, total_beahvior_info_out)) {
diff --git a/src/audio_core/info_updater.h b/src/audio_core/info_updater.h
index 06f9d770f..d315c91ed 100644
--- a/src/audio_core/info_updater.h
+++ b/src/audio_core/info_updater.h
@@ -21,8 +21,8 @@ class SplitterContext;
21class InfoUpdater { 21class InfoUpdater {
22public: 22public:
23 // TODO(ogniK): Pass process handle when we support it 23 // TODO(ogniK): Pass process handle when we support it
24 InfoUpdater(const std::vector<u8>& in_params, std::vector<u8>& out_params, 24 InfoUpdater(const std::vector<u8>& in_params_, std::vector<u8>& out_params_,
25 BehaviorInfo& behavior_info); 25 BehaviorInfo& behavior_info_);
26 ~InfoUpdater(); 26 ~InfoUpdater();
27 27
28 bool UpdateBehaviorInfo(BehaviorInfo& in_behavior_info); 28 bool UpdateBehaviorInfo(BehaviorInfo& in_behavior_info);
diff --git a/src/audio_core/memory_pool.cpp b/src/audio_core/memory_pool.cpp
index 5a3453063..6b6908d26 100644
--- a/src/audio_core/memory_pool.cpp
+++ b/src/audio_core/memory_pool.cpp
@@ -10,11 +10,10 @@ namespace AudioCore {
10 10
11ServerMemoryPoolInfo::ServerMemoryPoolInfo() = default; 11ServerMemoryPoolInfo::ServerMemoryPoolInfo() = default;
12ServerMemoryPoolInfo::~ServerMemoryPoolInfo() = default; 12ServerMemoryPoolInfo::~ServerMemoryPoolInfo() = default;
13bool ServerMemoryPoolInfo::Update(const ServerMemoryPoolInfo::InParams& in_params, 13
14 ServerMemoryPoolInfo::OutParams& out_params) { 14bool ServerMemoryPoolInfo::Update(const InParams& in_params, OutParams& out_params) {
15 // Our state does not need to be changed 15 // Our state does not need to be changed
16 if (in_params.state != ServerMemoryPoolInfo::State::RequestAttach && 16 if (in_params.state != State::RequestAttach && in_params.state != State::RequestDetach) {
17 in_params.state != ServerMemoryPoolInfo::State::RequestDetach) {
18 return true; 17 return true;
19 } 18 }
20 19
@@ -32,11 +31,11 @@ bool ServerMemoryPoolInfo::Update(const ServerMemoryPoolInfo::InParams& in_param
32 return false; 31 return false;
33 } 32 }
34 33
35 if (in_params.state == ServerMemoryPoolInfo::State::RequestAttach) { 34 if (in_params.state == State::RequestAttach) {
36 cpu_address = in_params.address; 35 cpu_address = in_params.address;
37 size = in_params.size; 36 size = in_params.size;
38 used = true; 37 used = true;
39 out_params.state = ServerMemoryPoolInfo::State::Attached; 38 out_params.state = State::Attached;
40 } else { 39 } else {
41 // Unexpected address 40 // Unexpected address
42 if (cpu_address != in_params.address) { 41 if (cpu_address != in_params.address) {
@@ -54,7 +53,7 @@ bool ServerMemoryPoolInfo::Update(const ServerMemoryPoolInfo::InParams& in_param
54 cpu_address = 0; 53 cpu_address = 0;
55 size = 0; 54 size = 0;
56 used = false; 55 used = false;
57 out_params.state = ServerMemoryPoolInfo::State::Detached; 56 out_params.state = State::Detached;
58 } 57 }
59 return true; 58 return true;
60} 59}
diff --git a/src/audio_core/memory_pool.h b/src/audio_core/memory_pool.h
index 8ac503f1c..3e9e777ae 100644
--- a/src/audio_core/memory_pool.h
+++ b/src/audio_core/memory_pool.h
@@ -28,19 +28,18 @@ public:
28 struct InParams { 28 struct InParams {
29 u64_le address{}; 29 u64_le address{};
30 u64_le size{}; 30 u64_le size{};
31 ServerMemoryPoolInfo::State state{}; 31 State state{};
32 INSERT_PADDING_WORDS(3); 32 INSERT_PADDING_WORDS(3);
33 }; 33 };
34 static_assert(sizeof(ServerMemoryPoolInfo::InParams) == 0x20, "InParams are an invalid size"); 34 static_assert(sizeof(InParams) == 0x20, "InParams are an invalid size");
35 35
36 struct OutParams { 36 struct OutParams {
37 ServerMemoryPoolInfo::State state{}; 37 State state{};
38 INSERT_PADDING_WORDS(3); 38 INSERT_PADDING_WORDS(3);
39 }; 39 };
40 static_assert(sizeof(ServerMemoryPoolInfo::OutParams) == 0x10, "OutParams are an invalid size"); 40 static_assert(sizeof(OutParams) == 0x10, "OutParams are an invalid size");
41 41
42 bool Update(const ServerMemoryPoolInfo::InParams& in_params, 42 bool Update(const InParams& in_params, OutParams& out_params);
43 ServerMemoryPoolInfo::OutParams& out_params);
44 43
45private: 44private:
46 // There's another entry here which is the DSP address, however since we're not talking to the 45 // There's another entry here which is the DSP address, however since we're not talking to the
diff --git a/src/audio_core/mix_context.cpp b/src/audio_core/mix_context.cpp
index 042891490..4bca72eb0 100644
--- a/src/audio_core/mix_context.cpp
+++ b/src/audio_core/mix_context.cpp
@@ -53,7 +53,7 @@ void MixContext::UpdateDistancesFromFinalMix() {
53 auto mix_id = in_params.mix_id; 53 auto mix_id = in_params.mix_id;
54 // Needs to be referenced out of scope 54 // Needs to be referenced out of scope
55 s32 distance_to_final_mix{AudioCommon::FINAL_MIX}; 55 s32 distance_to_final_mix{AudioCommon::FINAL_MIX};
56 for (; distance_to_final_mix < info_count; distance_to_final_mix++) { 56 for (; distance_to_final_mix < static_cast<s32>(info_count); distance_to_final_mix++) {
57 if (mix_id == AudioCommon::FINAL_MIX) { 57 if (mix_id == AudioCommon::FINAL_MIX) {
58 // If we're at the final mix, we're done 58 // If we're at the final mix, we're done
59 break; 59 break;
@@ -77,7 +77,7 @@ void MixContext::UpdateDistancesFromFinalMix() {
77 } 77 }
78 78
79 // If we're out of range for our distance, mark it as no final mix 79 // If we're out of range for our distance, mark it as no final mix
80 if (distance_to_final_mix >= info_count) { 80 if (distance_to_final_mix >= static_cast<s32>(info_count)) {
81 distance_to_final_mix = AudioCommon::NO_FINAL_MIX; 81 distance_to_final_mix = AudioCommon::NO_FINAL_MIX;
82 } 82 }
83 83
diff --git a/src/audio_core/mix_context.h b/src/audio_core/mix_context.h
index 6a588eeb4..68bc673c6 100644
--- a/src/audio_core/mix_context.h
+++ b/src/audio_core/mix_context.h
@@ -62,17 +62,17 @@ public:
62 ServerMixInfo(); 62 ServerMixInfo();
63 ~ServerMixInfo(); 63 ~ServerMixInfo();
64 64
65 const ServerMixInfo::InParams& GetInParams() const; 65 [[nodiscard]] const ServerMixInfo::InParams& GetInParams() const;
66 ServerMixInfo::InParams& GetInParams(); 66 [[nodiscard]] ServerMixInfo::InParams& GetInParams();
67 67
68 bool Update(EdgeMatrix& edge_matrix, const MixInfo::InParams& mix_in, 68 bool Update(EdgeMatrix& edge_matrix, const MixInfo::InParams& mix_in,
69 BehaviorInfo& behavior_info, SplitterContext& splitter_context, 69 BehaviorInfo& behavior_info, SplitterContext& splitter_context,
70 EffectContext& effect_context); 70 EffectContext& effect_context);
71 bool HasAnyConnection() const; 71 [[nodiscard]] bool HasAnyConnection() const;
72 void Cleanup(); 72 void Cleanup();
73 void SetEffectCount(std::size_t count); 73 void SetEffectCount(std::size_t count);
74 void ResetEffectProcessingOrder(); 74 void ResetEffectProcessingOrder();
75 s32 GetEffectOrder(std::size_t i) const; 75 [[nodiscard]] s32 GetEffectOrder(std::size_t i) const;
76 76
77private: 77private:
78 std::vector<s32> effect_processing_order; 78 std::vector<s32> effect_processing_order;
@@ -91,15 +91,15 @@ public:
91 void SortInfo(); 91 void SortInfo();
92 bool TsortInfo(SplitterContext& splitter_context); 92 bool TsortInfo(SplitterContext& splitter_context);
93 93
94 std::size_t GetCount() const; 94 [[nodiscard]] std::size_t GetCount() const;
95 ServerMixInfo& GetInfo(std::size_t i); 95 [[nodiscard]] ServerMixInfo& GetInfo(std::size_t i);
96 const ServerMixInfo& GetInfo(std::size_t i) const; 96 [[nodiscard]] const ServerMixInfo& GetInfo(std::size_t i) const;
97 ServerMixInfo& GetSortedInfo(std::size_t i); 97 [[nodiscard]] ServerMixInfo& GetSortedInfo(std::size_t i);
98 const ServerMixInfo& GetSortedInfo(std::size_t i) const; 98 [[nodiscard]] const ServerMixInfo& GetSortedInfo(std::size_t i) const;
99 ServerMixInfo& GetFinalMixInfo(); 99 [[nodiscard]] ServerMixInfo& GetFinalMixInfo();
100 const ServerMixInfo& GetFinalMixInfo() const; 100 [[nodiscard]] const ServerMixInfo& GetFinalMixInfo() const;
101 EdgeMatrix& GetEdgeMatrix(); 101 [[nodiscard]] EdgeMatrix& GetEdgeMatrix();
102 const EdgeMatrix& GetEdgeMatrix() const; 102 [[nodiscard]] const EdgeMatrix& GetEdgeMatrix() const;
103 103
104private: 104private:
105 void CalcMixBufferOffset(); 105 void CalcMixBufferOffset();
diff --git a/src/audio_core/sink_context.cpp b/src/audio_core/sink_context.cpp
index 0882b411a..a69543696 100644
--- a/src/audio_core/sink_context.cpp
+++ b/src/audio_core/sink_context.cpp
@@ -5,17 +5,23 @@
5#include "audio_core/sink_context.h" 5#include "audio_core/sink_context.h"
6 6
7namespace AudioCore { 7namespace AudioCore {
8SinkContext::SinkContext(std::size_t sink_count) : sink_count(sink_count) {} 8SinkContext::SinkContext(std::size_t sink_count_) : sink_count{sink_count_} {}
9SinkContext::~SinkContext() = default; 9SinkContext::~SinkContext() = default;
10 10
11std::size_t SinkContext::GetCount() const { 11std::size_t SinkContext::GetCount() const {
12 return sink_count; 12 return sink_count;
13} 13}
14 14
15void SinkContext::UpdateMainSink(SinkInfo::InParams& in) { 15void SinkContext::UpdateMainSink(const SinkInfo::InParams& in) {
16 ASSERT(in.type == SinkTypes::Device);
17
18 has_downmix_coefs = in.device.down_matrix_enabled;
19 if (has_downmix_coefs) {
20 downmix_coefficients = in.device.down_matrix_coef;
21 }
16 in_use = in.in_use; 22 in_use = in.in_use;
17 use_count = in.device.input_count; 23 use_count = in.device.input_count;
18 std::memcpy(buffers.data(), in.device.input.data(), AudioCommon::MAX_CHANNEL_COUNT); 24 buffers = in.device.input;
19} 25}
20 26
21bool SinkContext::InUse() const { 27bool SinkContext::InUse() const {
@@ -28,4 +34,12 @@ std::vector<u8> SinkContext::OutputBuffers() const {
28 return buffer_ret; 34 return buffer_ret;
29} 35}
30 36
37bool SinkContext::HasDownMixingCoefficients() const {
38 return has_downmix_coefs;
39}
40
41const DownmixCoefficients& SinkContext::GetDownmixCoefficients() const {
42 return downmix_coefficients;
43}
44
31} // namespace AudioCore 45} // namespace AudioCore
diff --git a/src/audio_core/sink_context.h b/src/audio_core/sink_context.h
index d7aa72ba7..05541becb 100644
--- a/src/audio_core/sink_context.h
+++ b/src/audio_core/sink_context.h
@@ -11,6 +11,8 @@
11 11
12namespace AudioCore { 12namespace AudioCore {
13 13
14using DownmixCoefficients = std::array<float_le, 4>;
15
14enum class SinkTypes : u8 { 16enum class SinkTypes : u8 {
15 Invalid = 0, 17 Invalid = 0,
16 Device = 1, 18 Device = 1,
@@ -40,7 +42,7 @@ public:
40 bool in_use; 42 bool in_use;
41 INSERT_UNION_PADDING_BYTES(5); 43 INSERT_UNION_PADDING_BYTES(5);
42 }; 44 };
43 static_assert(sizeof(SinkInfo::CircularBufferIn) == 0x28, 45 static_assert(sizeof(CircularBufferIn) == 0x28,
44 "SinkInfo::CircularBufferIn is in invalid size"); 46 "SinkInfo::CircularBufferIn is in invalid size");
45 47
46 struct DeviceIn { 48 struct DeviceIn {
@@ -50,9 +52,9 @@ public:
50 std::array<u8, AudioCommon::MAX_CHANNEL_COUNT> input; 52 std::array<u8, AudioCommon::MAX_CHANNEL_COUNT> input;
51 INSERT_UNION_PADDING_BYTES(1); 53 INSERT_UNION_PADDING_BYTES(1);
52 bool down_matrix_enabled; 54 bool down_matrix_enabled;
53 std::array<float_le, 4> down_matrix_coef; 55 DownmixCoefficients down_matrix_coef;
54 }; 56 };
55 static_assert(sizeof(SinkInfo::DeviceIn) == 0x11c, "SinkInfo::DeviceIn is an invalid size"); 57 static_assert(sizeof(DeviceIn) == 0x11c, "SinkInfo::DeviceIn is an invalid size");
56 58
57 struct InParams { 59 struct InParams {
58 SinkTypes type{}; 60 SinkTypes type{};
@@ -62,28 +64,33 @@ public:
62 INSERT_PADDING_WORDS(6); 64 INSERT_PADDING_WORDS(6);
63 union { 65 union {
64 // std::array<u8, 0x120> raw{}; 66 // std::array<u8, 0x120> raw{};
65 SinkInfo::DeviceIn device; 67 DeviceIn device;
66 SinkInfo::CircularBufferIn circular_buffer; 68 CircularBufferIn circular_buffer;
67 }; 69 };
68 }; 70 };
69 static_assert(sizeof(SinkInfo::InParams) == 0x140, "SinkInfo::InParams are an invalid size!"); 71 static_assert(sizeof(InParams) == 0x140, "SinkInfo::InParams are an invalid size!");
70}; 72};
71 73
72class SinkContext { 74class SinkContext {
73public: 75public:
74 explicit SinkContext(std::size_t sink_count); 76 explicit SinkContext(std::size_t sink_count_);
75 ~SinkContext(); 77 ~SinkContext();
76 78
77 std::size_t GetCount() const; 79 [[nodiscard]] std::size_t GetCount() const;
80
81 void UpdateMainSink(const SinkInfo::InParams& in);
82 [[nodiscard]] bool InUse() const;
83 [[nodiscard]] std::vector<u8> OutputBuffers() const;
78 84
79 void UpdateMainSink(SinkInfo::InParams& in); 85 [[nodiscard]] bool HasDownMixingCoefficients() const;
80 bool InUse() const; 86 [[nodiscard]] const DownmixCoefficients& GetDownmixCoefficients() const;
81 std::vector<u8> OutputBuffers() const;
82 87
83private: 88private:
84 bool in_use{false}; 89 bool in_use{false};
85 s32 use_count{}; 90 s32 use_count{};
86 std::array<u8, AudioCommon::MAX_CHANNEL_COUNT> buffers{}; 91 std::array<u8, AudioCommon::MAX_CHANNEL_COUNT> buffers{};
87 std::size_t sink_count{}; 92 std::size_t sink_count{};
93 bool has_downmix_coefs{false};
94 DownmixCoefficients downmix_coefficients{};
88}; 95};
89} // namespace AudioCore 96} // namespace AudioCore
diff --git a/src/audio_core/splitter_context.cpp b/src/audio_core/splitter_context.cpp
index 79bb2f516..f4bcd0391 100644
--- a/src/audio_core/splitter_context.cpp
+++ b/src/audio_core/splitter_context.cpp
@@ -10,7 +10,7 @@
10 10
11namespace AudioCore { 11namespace AudioCore {
12 12
13ServerSplitterDestinationData::ServerSplitterDestinationData(s32 id) : id(id) {} 13ServerSplitterDestinationData::ServerSplitterDestinationData(s32 id_) : id{id_} {}
14ServerSplitterDestinationData::~ServerSplitterDestinationData() = default; 14ServerSplitterDestinationData::~ServerSplitterDestinationData() = default;
15 15
16void ServerSplitterDestinationData::Update(SplitterInfo::InDestinationParams& header) { 16void ServerSplitterDestinationData::Update(SplitterInfo::InDestinationParams& header) {
@@ -87,7 +87,7 @@ void ServerSplitterDestinationData::UpdateInternalState() {
87 needs_update = false; 87 needs_update = false;
88} 88}
89 89
90ServerSplitterInfo::ServerSplitterInfo(s32 id) : id(id) {} 90ServerSplitterInfo::ServerSplitterInfo(s32 id_) : id(id_) {}
91ServerSplitterInfo::~ServerSplitterInfo() = default; 91ServerSplitterInfo::~ServerSplitterInfo() = default;
92 92
93void ServerSplitterInfo::InitializeInfos() { 93void ServerSplitterInfo::InitializeInfos() {
@@ -121,7 +121,7 @@ const ServerSplitterDestinationData* ServerSplitterInfo::GetHead() const {
121} 121}
122 122
123ServerSplitterDestinationData* ServerSplitterInfo::GetData(std::size_t depth) { 123ServerSplitterDestinationData* ServerSplitterInfo::GetData(std::size_t depth) {
124 auto current_head = head; 124 auto* current_head = head;
125 for (std::size_t i = 0; i < depth; i++) { 125 for (std::size_t i = 0; i < depth; i++) {
126 if (current_head == nullptr) { 126 if (current_head == nullptr) {
127 return nullptr; 127 return nullptr;
@@ -132,7 +132,7 @@ ServerSplitterDestinationData* ServerSplitterInfo::GetData(std::size_t depth) {
132} 132}
133 133
134const ServerSplitterDestinationData* ServerSplitterInfo::GetData(std::size_t depth) const { 134const ServerSplitterDestinationData* ServerSplitterInfo::GetData(std::size_t depth) const {
135 auto current_head = head; 135 auto* current_head = head;
136 for (std::size_t i = 0; i < depth; i++) { 136 for (std::size_t i = 0; i < depth; i++) {
137 if (current_head == nullptr) { 137 if (current_head == nullptr) {
138 return nullptr; 138 return nullptr;
@@ -245,7 +245,7 @@ ServerSplitterDestinationData* SplitterContext::GetDestinationData(std::size_t i
245const ServerSplitterDestinationData* SplitterContext::GetDestinationData(std::size_t info, 245const ServerSplitterDestinationData* SplitterContext::GetDestinationData(std::size_t info,
246 std::size_t data) const { 246 std::size_t data) const {
247 ASSERT(info < info_count); 247 ASSERT(info < info_count);
248 auto& cur_info = GetInfo(info); 248 const auto& cur_info = GetInfo(info);
249 return cur_info.GetData(data); 249 return cur_info.GetData(data);
250} 250}
251 251
@@ -267,11 +267,11 @@ std::size_t SplitterContext::GetDataCount() const {
267 return data_count; 267 return data_count;
268} 268}
269 269
270void SplitterContext::Setup(std::size_t _info_count, std::size_t _data_count, 270void SplitterContext::Setup(std::size_t info_count_, std::size_t data_count_,
271 bool is_splitter_bug_fixed) { 271 bool is_splitter_bug_fixed) {
272 272
273 info_count = _info_count; 273 info_count = info_count_;
274 data_count = _data_count; 274 data_count = data_count_;
275 275
276 for (std::size_t i = 0; i < info_count; i++) { 276 for (std::size_t i = 0; i < info_count; i++) {
277 auto& splitter = infos.emplace_back(static_cast<s32>(i)); 277 auto& splitter = infos.emplace_back(static_cast<s32>(i));
@@ -306,7 +306,7 @@ bool SplitterContext::UpdateInfo(const std::vector<u8>& input, std::size_t& inpu
306 break; 306 break;
307 } 307 }
308 308
309 if (header.send_id < 0 || header.send_id > info_count) { 309 if (header.send_id < 0 || static_cast<std::size_t>(header.send_id) > info_count) {
310 LOG_ERROR(Audio, "Bad splitter data id"); 310 LOG_ERROR(Audio, "Bad splitter data id");
311 break; 311 break;
312 } 312 }
@@ -348,7 +348,7 @@ bool SplitterContext::UpdateData(const std::vector<u8>& input, std::size_t& inpu
348 break; 348 break;
349 } 349 }
350 350
351 if (header.splitter_id < 0 || header.splitter_id > data_count) { 351 if (header.splitter_id < 0 || static_cast<std::size_t>(header.splitter_id) > data_count) {
352 LOG_ERROR(Audio, "Bad splitter data id"); 352 LOG_ERROR(Audio, "Bad splitter data id");
353 break; 353 break;
354 } 354 }
@@ -364,7 +364,7 @@ bool SplitterContext::RecomposeDestination(ServerSplitterInfo& info,
364 // Clear our current destinations 364 // Clear our current destinations
365 auto* current_head = info.GetHead(); 365 auto* current_head = info.GetHead();
366 while (current_head != nullptr) { 366 while (current_head != nullptr) {
367 auto next_head = current_head->GetNextDestination(); 367 auto* next_head = current_head->GetNextDestination();
368 current_head->SetNextDestination(nullptr); 368 current_head->SetNextDestination(nullptr);
369 current_head = next_head; 369 current_head = next_head;
370 } 370 }
@@ -434,7 +434,7 @@ const std::vector<s32>& NodeStates::GetIndexList() const {
434} 434}
435 435
436void NodeStates::PushTsortResult(s32 index) { 436void NodeStates::PushTsortResult(s32 index) {
437 ASSERT(index < node_count); 437 ASSERT(index < static_cast<s32>(node_count));
438 index_list[index_pos++] = index; 438 index_list[index_pos++] = index;
439} 439}
440 440
@@ -471,8 +471,8 @@ bool NodeStates::DepthFirstSearch(EdgeMatrix& edge_matrix) {
471 continue; 471 continue;
472 } 472 }
473 473
474 const auto node_count = edge_matrix.GetNodeCount(); 474 const auto edge_node_count = edge_matrix.GetNodeCount();
475 for (s32 j = 0; j < static_cast<s32>(node_count); j++) { 475 for (s32 j = 0; j < static_cast<s32>(edge_node_count); j++) {
476 // Check if our node is connected to our edge matrix 476 // Check if our node is connected to our edge matrix
477 if (!edge_matrix.Connected(current_stack_index, j)) { 477 if (!edge_matrix.Connected(current_stack_index, j)) {
478 continue; 478 continue;
diff --git a/src/audio_core/splitter_context.h b/src/audio_core/splitter_context.h
index ea6239fdb..b490627f5 100644
--- a/src/audio_core/splitter_context.h
+++ b/src/audio_core/splitter_context.h
@@ -63,7 +63,7 @@ public:
63 NodeStates(); 63 NodeStates();
64 ~NodeStates(); 64 ~NodeStates();
65 65
66 void Initialize(std::size_t _node_count); 66 void Initialize(std::size_t node_count_);
67 bool Tsort(EdgeMatrix& edge_matrix); 67 bool Tsort(EdgeMatrix& edge_matrix);
68 std::size_t GetIndexPos() const; 68 std::size_t GetIndexPos() const;
69 const std::vector<s32>& GetIndexList() const; 69 const std::vector<s32>& GetIndexList() const;
@@ -72,15 +72,15 @@ private:
72 void PushTsortResult(s32 index); 72 void PushTsortResult(s32 index);
73 bool DepthFirstSearch(EdgeMatrix& edge_matrix); 73 bool DepthFirstSearch(EdgeMatrix& edge_matrix);
74 void ResetState(); 74 void ResetState();
75 void UpdateState(NodeStates::State state, std::size_t i); 75 void UpdateState(State state, std::size_t i);
76 NodeStates::State GetState(std::size_t i); 76 State GetState(std::size_t i);
77 77
78 std::size_t node_count{}; 78 std::size_t node_count{};
79 std::vector<bool> was_node_found{}; 79 std::vector<bool> was_node_found{};
80 std::vector<bool> was_node_completed{}; 80 std::vector<bool> was_node_completed{};
81 std::size_t index_pos{}; 81 std::size_t index_pos{};
82 std::vector<s32> index_list{}; 82 std::vector<s32> index_list{};
83 NodeStates::Stack index_stack{}; 83 Stack index_stack{};
84}; 84};
85 85
86enum class SplitterMagic : u32_le { 86enum class SplitterMagic : u32_le {
@@ -97,8 +97,7 @@ public:
97 s32_le data_count{}; 97 s32_le data_count{};
98 INSERT_PADDING_WORDS(5); 98 INSERT_PADDING_WORDS(5);
99 }; 99 };
100 static_assert(sizeof(SplitterInfo::InHeader) == 0x20, 100 static_assert(sizeof(InHeader) == 0x20, "SplitterInfo::InHeader is an invalid size");
101 "SplitterInfo::InHeader is an invalid size");
102 101
103 struct InInfoPrams { 102 struct InInfoPrams {
104 SplitterMagic magic{}; 103 SplitterMagic magic{};
@@ -107,8 +106,7 @@ public:
107 s32_le length{}; 106 s32_le length{};
108 s32_le resource_id_base{}; 107 s32_le resource_id_base{};
109 }; 108 };
110 static_assert(sizeof(SplitterInfo::InInfoPrams) == 0x14, 109 static_assert(sizeof(InInfoPrams) == 0x14, "SplitterInfo::InInfoPrams is an invalid size");
111 "SplitterInfo::InInfoPrams is an invalid size");
112 110
113 struct InDestinationParams { 111 struct InDestinationParams {
114 SplitterMagic magic{}; 112 SplitterMagic magic{};
@@ -118,13 +116,13 @@ public:
118 bool in_use{}; 116 bool in_use{};
119 INSERT_PADDING_BYTES(3); 117 INSERT_PADDING_BYTES(3);
120 }; 118 };
121 static_assert(sizeof(SplitterInfo::InDestinationParams) == 0x70, 119 static_assert(sizeof(InDestinationParams) == 0x70,
122 "SplitterInfo::InDestinationParams is an invalid size"); 120 "SplitterInfo::InDestinationParams is an invalid size");
123}; 121};
124 122
125class ServerSplitterDestinationData { 123class ServerSplitterDestinationData {
126public: 124public:
127 explicit ServerSplitterDestinationData(s32 id); 125 explicit ServerSplitterDestinationData(s32 id_);
128 ~ServerSplitterDestinationData(); 126 ~ServerSplitterDestinationData();
129 127
130 void Update(SplitterInfo::InDestinationParams& header); 128 void Update(SplitterInfo::InDestinationParams& header);
@@ -153,7 +151,7 @@ private:
153 151
154class ServerSplitterInfo { 152class ServerSplitterInfo {
155public: 153public:
156 explicit ServerSplitterInfo(s32 id); 154 explicit ServerSplitterInfo(s32 id_);
157 ~ServerSplitterInfo(); 155 ~ServerSplitterInfo();
158 156
159 void InitializeInfos(); 157 void InitializeInfos();
diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp
index cb33926bc..afe68c9ed 100644
--- a/src/audio_core/stream.cpp
+++ b/src/audio_core/stream.cpp
@@ -12,7 +12,6 @@
12#include "common/assert.h" 12#include "common/assert.h"
13#include "common/logging/log.h" 13#include "common/logging/log.h"
14#include "core/core_timing.h" 14#include "core/core_timing.h"
15#include "core/core_timing_util.h"
16#include "core/settings.h" 15#include "core/settings.h"
17 16
18namespace AudioCore { 17namespace AudioCore {
@@ -32,10 +31,10 @@ u32 Stream::GetNumChannels() const {
32 return {}; 31 return {};
33} 32}
34 33
35Stream::Stream(Core::Timing::CoreTiming& core_timing, u32 sample_rate, Format format, 34Stream::Stream(Core::Timing::CoreTiming& core_timing_, u32 sample_rate_, Format format_,
36 ReleaseCallback&& release_callback, SinkStream& sink_stream, std::string&& name_) 35 ReleaseCallback&& release_callback_, SinkStream& sink_stream_, std::string&& name_)
37 : sample_rate{sample_rate}, format{format}, release_callback{std::move(release_callback)}, 36 : sample_rate{sample_rate_}, format{format_}, release_callback{std::move(release_callback_)},
38 sink_stream{sink_stream}, core_timing{core_timing}, name{std::move(name_)} { 37 sink_stream{sink_stream_}, core_timing{core_timing_}, name{std::move(name_)} {
39 release_event = 38 release_event =
40 Core::Timing::CreateEvent(name, [this](std::uintptr_t, std::chrono::nanoseconds ns_late) { 39 Core::Timing::CreateEvent(name, [this](std::uintptr_t, std::chrono::nanoseconds ns_late) {
41 ReleaseActiveBuffer(ns_late); 40 ReleaseActiveBuffer(ns_late);
@@ -123,7 +122,7 @@ bool Stream::QueueBuffer(BufferPtr&& buffer) {
123 return false; 122 return false;
124} 123}
125 124
126bool Stream::ContainsBuffer(Buffer::Tag tag) const { 125bool Stream::ContainsBuffer([[maybe_unused]] Buffer::Tag tag) const {
127 UNIMPLEMENTED(); 126 UNIMPLEMENTED();
128 return {}; 127 return {};
129} 128}
@@ -131,7 +130,25 @@ bool Stream::ContainsBuffer(Buffer::Tag tag) const {
131std::vector<Buffer::Tag> Stream::GetTagsAndReleaseBuffers(std::size_t max_count) { 130std::vector<Buffer::Tag> Stream::GetTagsAndReleaseBuffers(std::size_t max_count) {
132 std::vector<Buffer::Tag> tags; 131 std::vector<Buffer::Tag> tags;
133 for (std::size_t count = 0; count < max_count && !released_buffers.empty(); ++count) { 132 for (std::size_t count = 0; count < max_count && !released_buffers.empty(); ++count) {
134 tags.push_back(released_buffers.front()->GetTag()); 133 if (released_buffers.front()) {
134 tags.push_back(released_buffers.front()->GetTag());
135 } else {
136 ASSERT_MSG(false, "Invalid tag in released_buffers!");
137 }
138 released_buffers.pop();
139 }
140 return tags;
141}
142
143std::vector<Buffer::Tag> Stream::GetTagsAndReleaseBuffers() {
144 std::vector<Buffer::Tag> tags;
145 tags.reserve(released_buffers.size());
146 while (!released_buffers.empty()) {
147 if (released_buffers.front()) {
148 tags.push_back(released_buffers.front()->GetTag());
149 } else {
150 ASSERT_MSG(false, "Invalid tag in released_buffers!");
151 }
135 released_buffers.pop(); 152 released_buffers.pop();
136 } 153 }
137 return tags; 154 return tags;
diff --git a/src/audio_core/stream.h b/src/audio_core/stream.h
index 6437b8591..506ac536b 100644
--- a/src/audio_core/stream.h
+++ b/src/audio_core/stream.h
@@ -44,8 +44,8 @@ public:
44 /// Callback function type, used to change guest state on a buffer being released 44 /// Callback function type, used to change guest state on a buffer being released
45 using ReleaseCallback = std::function<void()>; 45 using ReleaseCallback = std::function<void()>;
46 46
47 Stream(Core::Timing::CoreTiming& core_timing, u32 sample_rate, Format format, 47 Stream(Core::Timing::CoreTiming& core_timing_, u32 sample_rate_, Format format_,
48 ReleaseCallback&& release_callback, SinkStream& sink_stream, std::string&& name_); 48 ReleaseCallback&& release_callback_, SinkStream& sink_stream_, std::string&& name_);
49 49
50 /// Plays the audio stream 50 /// Plays the audio stream
51 void Play(); 51 void Play();
@@ -57,37 +57,40 @@ public:
57 bool QueueBuffer(BufferPtr&& buffer); 57 bool QueueBuffer(BufferPtr&& buffer);
58 58
59 /// Returns true if the audio stream contains a buffer with the specified tag 59 /// Returns true if the audio stream contains a buffer with the specified tag
60 bool ContainsBuffer(Buffer::Tag tag) const; 60 [[nodiscard]] bool ContainsBuffer(Buffer::Tag tag) const;
61 61
62 /// Returns a vector of recently released buffers specified by tag 62 /// Returns a vector of recently released buffers specified by tag
63 std::vector<Buffer::Tag> GetTagsAndReleaseBuffers(std::size_t max_count); 63 [[nodiscard]] std::vector<Buffer::Tag> GetTagsAndReleaseBuffers(std::size_t max_count);
64
65 /// Returns a vector of all recently released buffers specified by tag
66 [[nodiscard]] std::vector<Buffer::Tag> GetTagsAndReleaseBuffers();
64 67
65 void SetVolume(float volume); 68 void SetVolume(float volume);
66 69
67 float GetVolume() const { 70 [[nodiscard]] float GetVolume() const {
68 return game_volume; 71 return game_volume;
69 } 72 }
70 73
71 /// Returns true if the stream is currently playing 74 /// Returns true if the stream is currently playing
72 bool IsPlaying() const { 75 [[nodiscard]] bool IsPlaying() const {
73 return state == State::Playing; 76 return state == State::Playing;
74 } 77 }
75 78
76 /// Returns the number of queued buffers 79 /// Returns the number of queued buffers
77 std::size_t GetQueueSize() const { 80 [[nodiscard]] std::size_t GetQueueSize() const {
78 return queued_buffers.size(); 81 return queued_buffers.size();
79 } 82 }
80 83
81 /// Gets the sample rate 84 /// Gets the sample rate
82 u32 GetSampleRate() const { 85 [[nodiscard]] u32 GetSampleRate() const {
83 return sample_rate; 86 return sample_rate;
84 } 87 }
85 88
86 /// Gets the number of channels 89 /// Gets the number of channels
87 u32 GetNumChannels() const; 90 [[nodiscard]] u32 GetNumChannels() const;
88 91
89 /// Get the state 92 /// Get the state
90 State GetState() const; 93 [[nodiscard]] State GetState() const;
91 94
92private: 95private:
93 /// Plays the next queued buffer in the audio stream, starting playback if necessary 96 /// Plays the next queued buffer in the audio stream, starting playback if necessary
@@ -97,7 +100,7 @@ private:
97 void ReleaseActiveBuffer(std::chrono::nanoseconds ns_late = {}); 100 void ReleaseActiveBuffer(std::chrono::nanoseconds ns_late = {});
98 101
99 /// Gets the number of core cycles when the specified buffer will be released 102 /// Gets the number of core cycles when the specified buffer will be released
100 std::chrono::nanoseconds GetBufferReleaseNS(const Buffer& buffer) const; 103 [[nodiscard]] std::chrono::nanoseconds GetBufferReleaseNS(const Buffer& buffer) const;
101 104
102 u32 sample_rate; ///< Sample rate of the stream 105 u32 sample_rate; ///< Sample rate of the stream
103 Format format; ///< Format of the stream 106 Format format; ///< Format of the stream
diff --git a/src/audio_core/voice_context.cpp b/src/audio_core/voice_context.cpp
index 1d8f69844..867b8fc6b 100644
--- a/src/audio_core/voice_context.cpp
+++ b/src/audio_core/voice_context.cpp
@@ -8,7 +8,7 @@
8 8
9namespace AudioCore { 9namespace AudioCore {
10 10
11ServerVoiceChannelResource::ServerVoiceChannelResource(s32 id) : id(id) {} 11ServerVoiceChannelResource::ServerVoiceChannelResource(s32 id_) : id(id_) {}
12ServerVoiceChannelResource::~ServerVoiceChannelResource() = default; 12ServerVoiceChannelResource::~ServerVoiceChannelResource() = default;
13 13
14bool ServerVoiceChannelResource::InUse() const { 14bool ServerVoiceChannelResource::InUse() const {
@@ -128,7 +128,10 @@ void ServerVoiceInfo::UpdateParameters(const VoiceInfo::InParams& voice_in,
128 in_params.wave_buffer_count = voice_in.wave_buffer_count; 128 in_params.wave_buffer_count = voice_in.wave_buffer_count;
129 in_params.wave_bufffer_head = voice_in.wave_buffer_head; 129 in_params.wave_bufffer_head = voice_in.wave_buffer_head;
130 if (behavior_info.IsFlushVoiceWaveBuffersSupported()) { 130 if (behavior_info.IsFlushVoiceWaveBuffersSupported()) {
131 in_params.wave_buffer_flush_request_count += voice_in.wave_buffer_flush_request_count; 131 const auto in_request_count = in_params.wave_buffer_flush_request_count;
132 const auto voice_request_count = voice_in.wave_buffer_flush_request_count;
133 in_params.wave_buffer_flush_request_count =
134 static_cast<u8>(in_request_count + voice_request_count);
132 } 135 }
133 in_params.mix_id = voice_in.mix_id; 136 in_params.mix_id = voice_in.mix_id;
134 if (behavior_info.IsSplitterSupported()) { 137 if (behavior_info.IsSplitterSupported()) {
@@ -206,7 +209,8 @@ void ServerVoiceInfo::UpdateWaveBuffers(
206 209
207void ServerVoiceInfo::UpdateWaveBuffer(ServerWaveBuffer& out_wavebuffer, 210void ServerVoiceInfo::UpdateWaveBuffer(ServerWaveBuffer& out_wavebuffer,
208 const WaveBuffer& in_wave_buffer, SampleFormat sample_format, 211 const WaveBuffer& in_wave_buffer, SampleFormat sample_format,
209 bool is_buffer_valid, BehaviorInfo& behavior_info) { 212 bool is_buffer_valid,
213 [[maybe_unused]] BehaviorInfo& behavior_info) {
210 if (!is_buffer_valid && out_wavebuffer.sent_to_dsp) { 214 if (!is_buffer_valid && out_wavebuffer.sent_to_dsp) {
211 out_wavebuffer.buffer_address = 0; 215 out_wavebuffer.buffer_address = 0;
212 out_wavebuffer.buffer_size = 0; 216 out_wavebuffer.buffer_size = 0;
@@ -397,7 +401,7 @@ bool ServerVoiceInfo::HasValidWaveBuffer(const VoiceState* state) const {
397 return std::find(valid_wb.begin(), valid_wb.end(), true) != valid_wb.end(); 401 return std::find(valid_wb.begin(), valid_wb.end(), true) != valid_wb.end();
398} 402}
399 403
400VoiceContext::VoiceContext(std::size_t voice_count) : voice_count(voice_count) { 404VoiceContext::VoiceContext(std::size_t voice_count_) : voice_count{voice_count_} {
401 for (std::size_t i = 0; i < voice_count; i++) { 405 for (std::size_t i = 0; i < voice_count; i++) {
402 voice_channel_resources.emplace_back(static_cast<s32>(i)); 406 voice_channel_resources.emplace_back(static_cast<s32>(i));
403 sorted_voice_info.push_back(&voice_info.emplace_back()); 407 sorted_voice_info.push_back(&voice_info.emplace_back());
@@ -488,11 +492,11 @@ s32 VoiceContext::DecodePcm16(s32* output_buffer, ServerWaveBuffer* wave_buffer,
488 492
489 // Fast path 493 // Fast path
490 if (channel_count == 1) { 494 if (channel_count == 1) {
491 for (std::size_t i = 0; i < samples_processed; i++) { 495 for (std::ptrdiff_t i = 0; i < samples_processed; i++) {
492 output_buffer[i] = buffer_data[i]; 496 output_buffer[i] = buffer_data[i];
493 } 497 }
494 } else { 498 } else {
495 for (std::size_t i = 0; i < samples_processed; i++) { 499 for (std::ptrdiff_t i = 0; i < samples_processed; i++) {
496 output_buffer[i] = buffer_data[i * channel_count + channel]; 500 output_buffer[i] = buffer_data[i * channel_count + channel];
497 } 501 }
498 } 502 }
diff --git a/src/audio_core/voice_context.h b/src/audio_core/voice_context.h
index 59d3d7dfb..863248761 100644
--- a/src/audio_core/voice_context.h
+++ b/src/audio_core/voice_context.h
@@ -118,12 +118,12 @@ public:
118 bool in_use{}; 118 bool in_use{};
119 INSERT_PADDING_BYTES(11); 119 INSERT_PADDING_BYTES(11);
120 }; 120 };
121 static_assert(sizeof(VoiceChannelResource::InParams) == 0x70, "InParams is an invalid size"); 121 static_assert(sizeof(InParams) == 0x70, "InParams is an invalid size");
122}; 122};
123 123
124class ServerVoiceChannelResource { 124class ServerVoiceChannelResource {
125public: 125public:
126 explicit ServerVoiceChannelResource(s32 id); 126 explicit ServerVoiceChannelResource(s32 id_);
127 ~ServerVoiceChannelResource(); 127 ~ServerVoiceChannelResource();
128 128
129 bool InUse() const; 129 bool InUse() const;
@@ -174,7 +174,7 @@ public:
174 BehaviorFlags behavior_flags{}; 174 BehaviorFlags behavior_flags{};
175 INSERT_PADDING_BYTES(16); 175 INSERT_PADDING_BYTES(16);
176 }; 176 };
177 static_assert(sizeof(VoiceInfo::InParams) == 0x170, "InParams is an invalid size"); 177 static_assert(sizeof(InParams) == 0x170, "InParams is an invalid size");
178 178
179 struct OutParams { 179 struct OutParams {
180 u64_le played_sample_count{}; 180 u64_le played_sample_count{};
@@ -182,7 +182,7 @@ public:
182 u8 voice_dropped{}; 182 u8 voice_dropped{};
183 INSERT_PADDING_BYTES(3); 183 INSERT_PADDING_BYTES(3);
184 }; 184 };
185 static_assert(sizeof(VoiceInfo::OutParams) == 0x10, "OutParams is an invalid size"); 185 static_assert(sizeof(OutParams) == 0x10, "OutParams is an invalid size");
186}; 186};
187 187
188class ServerVoiceInfo { 188class ServerVoiceInfo {
@@ -263,7 +263,7 @@ private:
263 263
264class VoiceContext { 264class VoiceContext {
265public: 265public:
266 VoiceContext(std::size_t voice_count); 266 explicit VoiceContext(std::size_t voice_count_);
267 ~VoiceContext(); 267 ~VoiceContext();
268 268
269 std::size_t GetVoiceCount() const; 269 std::size_t GetVoiceCount() const;