diff options
| author | 2021-01-10 22:09:56 -0700 | |
|---|---|---|
| committer | 2021-01-10 22:09:56 -0700 | |
| commit | 7a3c884e39fccfbb498b855080bffabc9ce2e7f1 (patch) | |
| tree | 5056f9406dec188439cb0deb87603498243a9412 /src/audio_core | |
| parent | More forgetting... duh (diff) | |
| parent | Merge pull request #5229 from Morph1984/fullscreen-opt (diff) | |
| download | yuzu-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')
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 | ||
| 45 | create_target_directory_groups(audio_core) | 45 | create_target_directory_groups(audio_core) |
| 46 | 46 | ||
| 47 | if (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 | ) | ||
| 63 | endif() | ||
| 64 | |||
| 47 | target_link_libraries(audio_core PUBLIC common core) | 65 | target_link_libraries(audio_core PUBLIC common core) |
| 48 | target_link_libraries(audio_core PRIVATE SoundTouch) | 66 | target_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 | ||
| 32 | Filter::Filter() : Filter(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) {} | 32 | Filter::Filter() : Filter(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) {} |
| 33 | 33 | ||
| 34 | Filter::Filter(double a0, double a1, double a2, double b0, double b1, double b2) | 34 | Filter::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 | ||
| 37 | void Filter::Process(std::vector<s16>& signal) { | 37 | void 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. |
| 57 | static double CascadingBiquadQ(std::size_t total_count, std::size_t index) { | 57 | static 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 | ||
| 70 | CascadingFilter::CascadingFilter() = default; | 71 | CascadingFilter::CascadingFilter() = default; |
| 71 | CascadingFilter::CascadingFilter(std::vector<Filter> filters) : filters(std::move(filters)) {} | 72 | CascadingFilter::CascadingFilter(std::vector<Filter> filters_) : filters(std::move(filters_)) {} |
| 72 | 73 | ||
| 73 | void CascadingFilter::Process(std::vector<s16>& signal) { | 74 | void 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 | ||
| 46 | std::vector<Buffer::Tag> AudioOut::GetTagsAndReleaseBuffers(StreamPtr stream) { | ||
| 47 | return stream->GetTagsAndReleaseBuffers(); | ||
| 48 | } | ||
| 49 | |||
| 46 | void AudioOut::StartStream(StreamPtr stream) { | 50 | void 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 | ||
| 17 | namespace { | ||
| 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 | |||
| 20 | namespace AudioCore { | 70 | namespace AudioCore { |
| 21 | AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing, Core::Memory::Memory& memory_, | 71 | AudioRenderer::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 | ||
| 68 | static constexpr s16 ClampToS16(s32 value) { | ||
| 69 | return static_cast<s16>(std::clamp(value, -32768, 32767)); | ||
| 70 | } | ||
| 71 | |||
| 72 | ResultCode AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_params, | 115 | ResultCode 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 | ||
| 264 | void AudioRenderer::ReleaseAndQueueBuffers() { | 317 | void 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 | ||
| 27 | namespace Core::Timing { | 26 | namespace Core::Timing { |
| 28 | class CoreTiming; | 27 | class CoreTiming; |
| 29 | } | 28 | } |
| 30 | 29 | ||
| 31 | namespace Kernel { | ||
| 32 | class WritableEvent; | ||
| 33 | } | ||
| 34 | |||
| 35 | namespace Core::Memory { | 30 | namespace Core::Memory { |
| 36 | class Memory; | 31 | class Memory; |
| 37 | } | 32 | } |
| 38 | 33 | ||
| 39 | namespace AudioCore { | 34 | namespace AudioCore { |
| 40 | using DSPStateHolder = std::array<VoiceState*, 6>; | 35 | using DSPStateHolder = std::array<VoiceState*, AudioCommon::MAX_CHANNEL_COUNT>; |
| 41 | 36 | ||
| 42 | class AudioOut; | 37 | class AudioOut; |
| 43 | 38 | ||
| 44 | struct RendererInfo { | ||
| 45 | u64_le elasped_frame_count{}; | ||
| 46 | INSERT_PADDING_WORDS(2); | ||
| 47 | }; | ||
| 48 | static_assert(sizeof(RendererInfo) == 0x10, "RendererInfo is an invalid size"); | ||
| 49 | |||
| 50 | class AudioRenderer { | 39 | class AudioRenderer { |
| 51 | public: | 40 | public: |
| 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 | ||
| 66 | private: | 55 | private: |
| 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 | ||
| 60 | bool BehaviorInfo::IsAudioRenererProcessingTimeLimit80PercentSupported() const { | 60 | bool BehaviorInfo::IsAudioRendererProcessingTimeLimit80PercentSupported() const { |
| 61 | return AudioCommon::IsRevisionSupported(5, user_revision); | 61 | return AudioCommon::IsRevisionSupported(5, user_revision); |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | bool BehaviorInfo::IsAudioRenererProcessingTimeLimit75PercentSupported() const { | 64 | bool BehaviorInfo::IsAudioRendererProcessingTimeLimit75PercentSupported() const { |
| 65 | return AudioCommon::IsRevisionSupported(4, user_revision); | 65 | return AudioCommon::IsRevisionSupported(4, user_revision); |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | bool BehaviorInfo::IsAudioRenererProcessingTimeLimit70PercentSupported() const { | 68 | bool 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 | ||
| 64 | private: | 64 | private: |
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 { | |||
| 18 | public: | 18 | public: |
| 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 | */ |
| 41 | std::vector<s16> DecodeADPCM(const u8* const data, std::size_t size, const ADPCM_Coeff& coeff, | 41 | std::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 | ||
| 70 | CommandGenerator::CommandGenerator(AudioCommon::AudioRendererParameter& worker_params, | 70 | CommandGenerator::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 | ||
| 256 | void CommandGenerator::GenerateBiquadFilterCommandForVoice(ServerVoiceInfo& voice_info, | 256 | void 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 | ||
| 281 | void AudioCore::CommandGenerator::GenerateBiquadFilterCommand( | 282 | void 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 | ||
| 715 | s32 CommandGenerator::DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_state, | 720 | s32 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 | ||
| 13 | namespace Core::Memory { | 12 | namespace Core::Memory { |
| @@ -26,10 +25,10 @@ using MixVolumeBuffer = std::array<float, AudioCommon::MAX_MIX_BUFFERS>; | |||
| 26 | 25 | ||
| 27 | class CommandGenerator { | 26 | class CommandGenerator { |
| 28 | public: | 27 | public: |
| 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 | ||
| 51 | private: | 50 | private: |
| 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; | |||
| 21 | constexpr std::size_t MAX_WAVE_BUFFERS = 4; | 22 | constexpr std::size_t MAX_WAVE_BUFFERS = 4; |
| 22 | constexpr std::size_t MAX_SAMPLE_HISTORY = 4; | 23 | constexpr std::size_t MAX_SAMPLE_HISTORY = 4; |
| 23 | constexpr u32 STREAM_SAMPLE_RATE = 48000; | 24 | constexpr u32 STREAM_SAMPLE_RATE = 48000; |
| 24 | constexpr u32 STREAM_NUM_CHANNELS = 6; | 25 | constexpr u32 STREAM_NUM_CHANNELS = 2; |
| 25 | constexpr s32 NO_SPLITTER = -1; | 26 | constexpr s32 NO_SPLITTER = -1; |
| 26 | constexpr s32 NO_MIX = 0x7fffffff; | 27 | constexpr s32 NO_MIX = 0x7fffffff; |
| 27 | constexpr s32 NO_FINAL_MIX = std::numeric_limits<s32>::min(); | 28 | constexpr 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 | ||
| 22 | class CubebSinkStream final : public SinkStream { | 22 | class CubebSinkStream final : public SinkStream { |
| 23 | public: | 23 | public: |
| 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 | ||
| 193 | long CubebSinkStream::DataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer, | 196 | long 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 | ||
| 237 | void CubebSinkStream::StateCallback(cubeb_stream* stream, void* user_data, cubeb_state state) {} | 241 | void CubebSinkStream::StateCallback([[maybe_unused]] cubeb_stream* stream, |
| 242 | [[maybe_unused]] void* user_data, | ||
| 243 | [[maybe_unused]] cubeb_state state) {} | ||
| 238 | 244 | ||
| 239 | std::vector<std::string> ListCubebSinkDevices() { | 245 | std::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 | ||
| 15 | EffectContext::EffectContext(std::size_t effect_count) : effect_count(effect_count) { | 15 | EffectContext::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 | ||
| 64 | EffectStubbed::EffectStubbed() : EffectBase::EffectBase(EffectType::Invalid) {} | 64 | EffectStubbed::EffectStubbed() : EffectBase(EffectType::Invalid) {} |
| 65 | EffectStubbed::~EffectStubbed() = default; | 65 | EffectStubbed::~EffectStubbed() = default; |
| 66 | 66 | ||
| 67 | void EffectStubbed::Update(EffectInfo::InParams& in_params) {} | 67 | void EffectStubbed::Update([[maybe_unused]] EffectInfo::InParams& in_params) {} |
| 68 | void EffectStubbed::UpdateForCommandGeneration() {} | 68 | void EffectStubbed::UpdateForCommandGeneration() {} |
| 69 | 69 | ||
| 70 | EffectBase::EffectBase(EffectType effect_type) : effect_type(effect_type) {} | 70 | EffectBase::EffectBase(EffectType effect_type_) : effect_type(effect_type_) {} |
| 71 | EffectBase::~EffectBase() = default; | 71 | EffectBase::~EffectBase() = default; |
| 72 | 72 | ||
| 73 | UsageState EffectBase::GetUsage() const { | 73 | UsageState EffectBase::GetUsage() const { |
| @@ -90,32 +90,32 @@ s32 EffectBase::GetProcessingOrder() const { | |||
| 90 | return processing_order; | 90 | return processing_order; |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | EffectI3dl2Reverb::EffectI3dl2Reverb() : EffectGeneric::EffectGeneric(EffectType::I3dl2Reverb) {} | 93 | EffectI3dl2Reverb::EffectI3dl2Reverb() : EffectGeneric(EffectType::I3dl2Reverb) {} |
| 94 | EffectI3dl2Reverb::~EffectI3dl2Reverb() = default; | 94 | EffectI3dl2Reverb::~EffectI3dl2Reverb() = default; |
| 95 | 95 | ||
| 96 | void EffectI3dl2Reverb::Update(EffectInfo::InParams& in_params) { | 96 | void 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 | ||
| 132 | EffectBiquadFilter::EffectBiquadFilter() : EffectGeneric::EffectGeneric(EffectType::BiquadFilter) {} | 132 | EffectBiquadFilter::EffectBiquadFilter() : EffectGeneric(EffectType::BiquadFilter) {} |
| 133 | EffectBiquadFilter::~EffectBiquadFilter() = default; | 133 | EffectBiquadFilter::~EffectBiquadFilter() = default; |
| 134 | 134 | ||
| 135 | void EffectBiquadFilter::Update(EffectInfo::InParams& in_params) { | 135 | void 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 | ||
| 153 | EffectAuxInfo::EffectAuxInfo() : EffectGeneric::EffectGeneric(EffectType::Aux) {} | 153 | EffectAuxInfo::EffectAuxInfo() : EffectGeneric(EffectType::Aux) {} |
| 154 | EffectAuxInfo::~EffectAuxInfo() = default; | 154 | EffectAuxInfo::~EffectAuxInfo() = default; |
| 155 | 155 | ||
| 156 | void EffectAuxInfo::Update(EffectInfo::InParams& in_params) { | 156 | void EffectAuxInfo::Update(EffectInfo::InParams& in_params) { |
| @@ -184,48 +184,48 @@ void EffectAuxInfo::UpdateForCommandGeneration() { | |||
| 184 | } | 184 | } |
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | const VAddr EffectAuxInfo::GetSendInfo() const { | 187 | VAddr EffectAuxInfo::GetSendInfo() const { |
| 188 | return send_info; | 188 | return send_info; |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | const VAddr EffectAuxInfo::GetSendBuffer() const { | 191 | VAddr EffectAuxInfo::GetSendBuffer() const { |
| 192 | return send_buffer; | 192 | return send_buffer; |
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | const VAddr EffectAuxInfo::GetRecvInfo() const { | 195 | VAddr EffectAuxInfo::GetRecvInfo() const { |
| 196 | return recv_info; | 196 | return recv_info; |
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | const VAddr EffectAuxInfo::GetRecvBuffer() const { | 199 | VAddr EffectAuxInfo::GetRecvBuffer() const { |
| 200 | return recv_buffer; | 200 | return recv_buffer; |
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | EffectDelay::EffectDelay() : EffectGeneric::EffectGeneric(EffectType::Delay) {} | 203 | EffectDelay::EffectDelay() : EffectGeneric(EffectType::Delay) {} |
| 204 | EffectDelay::~EffectDelay() = default; | 204 | EffectDelay::~EffectDelay() = default; |
| 205 | 205 | ||
| 206 | void EffectDelay::Update(EffectInfo::InParams& in_params) { | 206 | void 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 | ||
| 242 | EffectBufferMixer::EffectBufferMixer() : EffectGeneric::EffectGeneric(EffectType::BufferMixer) {} | 242 | EffectBufferMixer::EffectBufferMixer() : EffectGeneric(EffectType::BufferMixer) {} |
| 243 | EffectBufferMixer::~EffectBufferMixer() = default; | 243 | EffectBufferMixer::~EffectBufferMixer() = default; |
| 244 | 244 | ||
| 245 | void EffectBufferMixer::Update(EffectInfo::InParams& in_params) { | 245 | void EffectBufferMixer::Update(EffectInfo::InParams& in_params) { |
| @@ -257,32 +257,32 @@ void EffectBufferMixer::UpdateForCommandGeneration() { | |||
| 257 | } | 257 | } |
| 258 | } | 258 | } |
| 259 | 259 | ||
| 260 | EffectReverb::EffectReverb() : EffectGeneric::EffectGeneric(EffectType::Reverb) {} | 260 | EffectReverb::EffectReverb() : EffectGeneric(EffectType::Reverb) {} |
| 261 | EffectReverb::~EffectReverb() = default; | 261 | EffectReverb::~EffectReverb() = default; |
| 262 | 262 | ||
| 263 | void EffectReverb::Update(EffectInfo::InParams& in_params) { | 263 | void 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 | ||
| 178 | struct AuxAddress { | 178 | struct AuxAddress { |
| @@ -184,16 +184,16 @@ struct AuxAddress { | |||
| 184 | 184 | ||
| 185 | class EffectBase { | 185 | class EffectBase { |
| 186 | public: | 186 | public: |
| 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 | ||
| 198 | protected: | 198 | protected: |
| 199 | UsageState usage{UsageState::Invalid}; | 199 | UsageState usage{UsageState::Invalid}; |
| @@ -206,8 +206,7 @@ protected: | |||
| 206 | template <typename T> | 206 | template <typename T> |
| 207 | class EffectGeneric : public EffectBase { | 207 | class EffectGeneric : public EffectBase { |
| 208 | public: | 208 | public: |
| 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: | |||
| 224 | class EffectStubbed : public EffectBase { | 223 | class EffectStubbed : public EffectBase { |
| 225 | public: | 224 | public: |
| 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: | |||
| 233 | class EffectI3dl2Reverb : public EffectGeneric<I3dl2ReverbParams> { | 232 | class EffectI3dl2Reverb : public EffectGeneric<I3dl2ReverbParams> { |
| 234 | public: | 233 | public: |
| 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: | |||
| 245 | class EffectBiquadFilter : public EffectGeneric<BiquadFilterParams> { | 244 | class EffectBiquadFilter : public EffectGeneric<BiquadFilterParams> { |
| 246 | public: | 245 | public: |
| 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: | |||
| 254 | class EffectAuxInfo : public EffectGeneric<AuxInfo> { | 253 | class EffectAuxInfo : public EffectGeneric<AuxInfo> { |
| 255 | public: | 254 | public: |
| 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 | ||
| 266 | private: | 265 | private: |
| 267 | VAddr send_info{}; | 266 | VAddr send_info{}; |
| @@ -275,7 +274,7 @@ private: | |||
| 275 | class EffectDelay : public EffectGeneric<DelayParams> { | 274 | class EffectDelay : public EffectGeneric<DelayParams> { |
| 276 | public: | 275 | public: |
| 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: | |||
| 287 | class EffectBufferMixer : public EffectGeneric<BufferMixerParams> { | 286 | class EffectBufferMixer : public EffectGeneric<BufferMixerParams> { |
| 288 | public: | 287 | public: |
| 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: | |||
| 296 | class EffectReverb : public EffectGeneric<ReverbParams> { | 295 | class EffectReverb : public EffectGeneric<ReverbParams> { |
| 297 | public: | 296 | public: |
| 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 | ||
| 308 | class EffectContext { | 307 | class EffectContext { |
| 309 | public: | 308 | public: |
| 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 | ||
| 318 | private: | 317 | private: |
| 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 | ||
| 15 | namespace AudioCore { | 15 | namespace AudioCore { |
| 16 | 16 | ||
| 17 | InfoUpdater::InfoUpdater(const std::vector<u8>& in_params, std::vector<u8>& out_params, | 17 | InfoUpdater::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 | ||
| 66 | bool InfoUpdater::UpdateMemoryPools(std::vector<ServerMemoryPoolInfo>& memory_pool_info) { | 66 | bool 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 | ||
| 138 | bool InfoUpdater::UpdateVoices(VoiceContext& voice_context, | 137 | bool 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 | ||
| 449 | bool InfoUpdater::UpdateErrorInfo(BehaviorInfo& in_behavior_info) { | 448 | bool 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; | |||
| 21 | class InfoUpdater { | 21 | class InfoUpdater { |
| 22 | public: | 22 | public: |
| 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 | ||
| 11 | ServerMemoryPoolInfo::ServerMemoryPoolInfo() = default; | 11 | ServerMemoryPoolInfo::ServerMemoryPoolInfo() = default; |
| 12 | ServerMemoryPoolInfo::~ServerMemoryPoolInfo() = default; | 12 | ServerMemoryPoolInfo::~ServerMemoryPoolInfo() = default; |
| 13 | bool ServerMemoryPoolInfo::Update(const ServerMemoryPoolInfo::InParams& in_params, | 13 | |
| 14 | ServerMemoryPoolInfo::OutParams& out_params) { | 14 | bool 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 | ||
| 45 | private: | 44 | private: |
| 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 | ||
| 77 | private: | 77 | private: |
| 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 | ||
| 104 | private: | 104 | private: |
| 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 | ||
| 7 | namespace AudioCore { | 7 | namespace AudioCore { |
| 8 | SinkContext::SinkContext(std::size_t sink_count) : sink_count(sink_count) {} | 8 | SinkContext::SinkContext(std::size_t sink_count_) : sink_count{sink_count_} {} |
| 9 | SinkContext::~SinkContext() = default; | 9 | SinkContext::~SinkContext() = default; |
| 10 | 10 | ||
| 11 | std::size_t SinkContext::GetCount() const { | 11 | std::size_t SinkContext::GetCount() const { |
| 12 | return sink_count; | 12 | return sink_count; |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | void SinkContext::UpdateMainSink(SinkInfo::InParams& in) { | 15 | void 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 | ||
| 21 | bool SinkContext::InUse() const { | 27 | bool 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 | ||
| 37 | bool SinkContext::HasDownMixingCoefficients() const { | ||
| 38 | return has_downmix_coefs; | ||
| 39 | } | ||
| 40 | |||
| 41 | const 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 | ||
| 12 | namespace AudioCore { | 12 | namespace AudioCore { |
| 13 | 13 | ||
| 14 | using DownmixCoefficients = std::array<float_le, 4>; | ||
| 15 | |||
| 14 | enum class SinkTypes : u8 { | 16 | enum 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 | ||
| 72 | class SinkContext { | 74 | class SinkContext { |
| 73 | public: | 75 | public: |
| 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 | ||
| 83 | private: | 88 | private: |
| 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 | ||
| 11 | namespace AudioCore { | 11 | namespace AudioCore { |
| 12 | 12 | ||
| 13 | ServerSplitterDestinationData::ServerSplitterDestinationData(s32 id) : id(id) {} | 13 | ServerSplitterDestinationData::ServerSplitterDestinationData(s32 id_) : id{id_} {} |
| 14 | ServerSplitterDestinationData::~ServerSplitterDestinationData() = default; | 14 | ServerSplitterDestinationData::~ServerSplitterDestinationData() = default; |
| 15 | 15 | ||
| 16 | void ServerSplitterDestinationData::Update(SplitterInfo::InDestinationParams& header) { | 16 | void ServerSplitterDestinationData::Update(SplitterInfo::InDestinationParams& header) { |
| @@ -87,7 +87,7 @@ void ServerSplitterDestinationData::UpdateInternalState() { | |||
| 87 | needs_update = false; | 87 | needs_update = false; |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | ServerSplitterInfo::ServerSplitterInfo(s32 id) : id(id) {} | 90 | ServerSplitterInfo::ServerSplitterInfo(s32 id_) : id(id_) {} |
| 91 | ServerSplitterInfo::~ServerSplitterInfo() = default; | 91 | ServerSplitterInfo::~ServerSplitterInfo() = default; |
| 92 | 92 | ||
| 93 | void ServerSplitterInfo::InitializeInfos() { | 93 | void ServerSplitterInfo::InitializeInfos() { |
| @@ -121,7 +121,7 @@ const ServerSplitterDestinationData* ServerSplitterInfo::GetHead() const { | |||
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | ServerSplitterDestinationData* ServerSplitterInfo::GetData(std::size_t depth) { | 123 | ServerSplitterDestinationData* 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 | ||
| 134 | const ServerSplitterDestinationData* ServerSplitterInfo::GetData(std::size_t depth) const { | 134 | const 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 | |||
| 245 | const ServerSplitterDestinationData* SplitterContext::GetDestinationData(std::size_t info, | 245 | const 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 | ||
| 270 | void SplitterContext::Setup(std::size_t _info_count, std::size_t _data_count, | 270 | void 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 | ||
| 436 | void NodeStates::PushTsortResult(s32 index) { | 436 | void 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 | ||
| 86 | enum class SplitterMagic : u32_le { | 86 | enum 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 | ||
| 125 | class ServerSplitterDestinationData { | 123 | class ServerSplitterDestinationData { |
| 126 | public: | 124 | public: |
| 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 | ||
| 154 | class ServerSplitterInfo { | 152 | class ServerSplitterInfo { |
| 155 | public: | 153 | public: |
| 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 | ||
| 18 | namespace AudioCore { | 17 | namespace AudioCore { |
| @@ -32,10 +31,10 @@ u32 Stream::GetNumChannels() const { | |||
| 32 | return {}; | 31 | return {}; |
| 33 | } | 32 | } |
| 34 | 33 | ||
| 35 | Stream::Stream(Core::Timing::CoreTiming& core_timing, u32 sample_rate, Format format, | 34 | Stream::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 | ||
| 126 | bool Stream::ContainsBuffer(Buffer::Tag tag) const { | 125 | bool 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 { | |||
| 131 | std::vector<Buffer::Tag> Stream::GetTagsAndReleaseBuffers(std::size_t max_count) { | 130 | std::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 | |||
| 143 | std::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 | ||
| 92 | private: | 95 | private: |
| 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 | ||
| 9 | namespace AudioCore { | 9 | namespace AudioCore { |
| 10 | 10 | ||
| 11 | ServerVoiceChannelResource::ServerVoiceChannelResource(s32 id) : id(id) {} | 11 | ServerVoiceChannelResource::ServerVoiceChannelResource(s32 id_) : id(id_) {} |
| 12 | ServerVoiceChannelResource::~ServerVoiceChannelResource() = default; | 12 | ServerVoiceChannelResource::~ServerVoiceChannelResource() = default; |
| 13 | 13 | ||
| 14 | bool ServerVoiceChannelResource::InUse() const { | 14 | bool 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 | ||
| 207 | void ServerVoiceInfo::UpdateWaveBuffer(ServerWaveBuffer& out_wavebuffer, | 210 | void 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 | ||
| 400 | VoiceContext::VoiceContext(std::size_t voice_count) : voice_count(voice_count) { | 404 | VoiceContext::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 | ||
| 124 | class ServerVoiceChannelResource { | 124 | class ServerVoiceChannelResource { |
| 125 | public: | 125 | public: |
| 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 | ||
| 188 | class ServerVoiceInfo { | 188 | class ServerVoiceInfo { |
| @@ -263,7 +263,7 @@ private: | |||
| 263 | 263 | ||
| 264 | class VoiceContext { | 264 | class VoiceContext { |
| 265 | public: | 265 | public: |
| 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; |