From 2de52e3af65e71df8a1ef00c9bcfcaa9f67330c3 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Sun, 7 Oct 2018 14:14:09 +1100 Subject: [PATCH 1/4] Fixed smo softlock --- src/audio_core/audio_renderer.cpp | 84 ++++++++++++++++++++++++++----- src/audio_core/audio_renderer.h | 49 ++++++++++++++++++ 2 files changed, 120 insertions(+), 13 deletions(-) diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp index 6f0ff953a3..9b7970d421 100644 --- a/src/audio_core/audio_renderer.cpp +++ b/src/audio_core/audio_renderer.cpp @@ -51,9 +51,30 @@ private: VoiceInfo info{}; }; +class AudioRenderer::EffectState { +public: + const EffectOutStatus& GetOutStatus() const { + return out_status; + } + + const EffectInStatus& GetInfo() const { + info; + } + + EffectInStatus& Info() { + return info; + } + + void UpdateState(); + +private: + EffectOutStatus out_status{}; + EffectInStatus info{}; +}; AudioRenderer::AudioRenderer(AudioRendererParameter params, Kernel::SharedPtr buffer_event) - : worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count) { + : worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count), + effects(params.effect_count) { audio_out = std::make_unique(); stream = audio_out->OpenStream(STREAM_SAMPLE_RATE, STREAM_NUM_CHANNELS, "AudioRenderer", @@ -96,11 +117,29 @@ std::vector AudioRenderer::UpdateAudioRenderer(const std::vector& input_ memory_pool_count * sizeof(MemoryPoolInfo)); // Copy VoiceInfo structs - std::size_t offset{sizeof(UpdateDataHeader) + config.behavior_size + config.memory_pools_size + - config.voice_resource_size}; + std::size_t voice_offset{sizeof(UpdateDataHeader) + config.behavior_size + + config.memory_pools_size + config.voice_resource_size}; for (auto& voice : voices) { - std::memcpy(&voice.Info(), input_params.data() + offset, sizeof(VoiceInfo)); - offset += sizeof(VoiceInfo); + std::memcpy(&voice.Info(), input_params.data() + voice_offset, sizeof(VoiceInfo)); + voice_offset += sizeof(VoiceInfo); + } + + std::size_t effect_offset{sizeof(UpdateDataHeader) + config.behavior_size + + config.memory_pools_size + config.voice_resource_size + + config.voices_size}; + for (auto& effect : effects) { + std::memcpy(&effect.Info(), input_params.data() + effect_offset, sizeof(EffectInStatus)); + effect_offset += sizeof(EffectInStatus); + } + + // Update memory pool state + std::vector memory_pool(memory_pool_count); + for (std::size_t index = 0; index < memory_pool.size(); ++index) { + if (mem_pool_info[index].pool_state == MemoryPoolStates::RequestAttach) { + memory_pool[index].state = MemoryPoolStates::Attached; + } else if (mem_pool_info[index].pool_state == MemoryPoolStates::RequestDetach) { + memory_pool[index].state = MemoryPoolStates::Detached; + } } // Update voices @@ -114,14 +153,8 @@ std::vector AudioRenderer::UpdateAudioRenderer(const std::vector& input_ } } - // Update memory pool state - std::vector memory_pool(memory_pool_count); - for (std::size_t index = 0; index < memory_pool.size(); ++index) { - if (mem_pool_info[index].pool_state == MemoryPoolStates::RequestAttach) { - memory_pool[index].state = MemoryPoolStates::Attached; - } else if (mem_pool_info[index].pool_state == MemoryPoolStates::RequestDetach) { - memory_pool[index].state = MemoryPoolStates::Detached; - } + for (auto& effect : effects) { + effect.UpdateState(); } // Release previous buffers and queue next ones for playback @@ -144,6 +177,14 @@ std::vector AudioRenderer::UpdateAudioRenderer(const std::vector& input_ voice_out_status_offset += sizeof(VoiceOutStatus); } + std::size_t effect_out_status_offset{ + sizeof(UpdateDataHeader) + response_data.memory_pools_size + response_data.voices_size + + response_data.voice_resource_size}; + for (const auto& effect : effects) { + std::memcpy(output_params.data() + effect_out_status_offset, &effect.GetOutStatus(), + sizeof(EffectOutStatus)); + effect_out_status_offset += sizeof(EffectOutStatus); + } return output_params; } @@ -249,6 +290,23 @@ void AudioRenderer::VoiceState::RefreshBuffer() { is_refresh_pending = false; } +void AudioRenderer::EffectState::UpdateState() { + if (info.is_new) { + out_status.state = EffectStatus::New; + } else { + if (info.type == Effect::Aux) { + ASSERT_MSG(Memory::Read32(info.aux_info.return_buffer_info) == 0, + "Aux buffers tried to update"); + ASSERT_MSG(Memory::Read32(info.aux_info.send_buffer_info) == 0, + "Aux buffers tried to update"); + ASSERT_MSG(Memory::Read32(info.aux_info.return_buffer_base) == 0, + "Aux buffers tried to update"); + ASSERT_MSG(Memory::Read32(info.aux_info.send_buffer_base) == 0, + "Aux buffers tried to update"); + } + } +} + static constexpr s16 ClampToS16(s32 value) { return static_cast(std::clamp(value, -32768, 32767)); } diff --git a/src/audio_core/audio_renderer.h b/src/audio_core/audio_renderer.h index dfef89e1d0..a2caeb118b 100644 --- a/src/audio_core/audio_renderer.h +++ b/src/audio_core/audio_renderer.h @@ -28,6 +28,16 @@ enum class PlayState : u8 { Paused = 2, }; +enum class Effect : u8 { + None = 0, + Aux = 2, +}; + +enum class EffectStatus : u8 { + None = 0, + New = 1, +}; + struct AudioRendererParameter { u32_le sample_rate; u32_le sample_count; @@ -128,6 +138,43 @@ struct VoiceOutStatus { }; static_assert(sizeof(VoiceOutStatus) == 0x10, "VoiceOutStatus has wrong size"); +struct AuxInfo { + std::array input_mix_buffers; + std::array output_mix_buffers; + u32_le mix_buffer_count; + u32_le sample_rate; // Stored in the aux buffer currently + u32_le sampe_count; + u64_le send_buffer_info; + u64_le send_buffer_base; + + u64_le return_buffer_info; + u64_le return_buffer_base; +}; +static_assert(sizeof(AuxInfo) == 0x60, "AuxInfo is an invalid size"); + +struct EffectInStatus { + Effect type; + u8 is_new; + u8 is_enabled; + INSERT_PADDING_BYTES(1); + u32_le mix_id; + u64_le buffer_base; + u64_le buffer_sz; + s32_le priority; + INSERT_PADDING_BYTES(4); + union { + std::array raw; + AuxInfo aux_info; + }; +}; +static_assert(sizeof(EffectInStatus) == 0xc0, "EffectInStatus is an invalid size"); + +struct EffectOutStatus { + EffectStatus state; + INSERT_PADDING_BYTES(15); +}; +static_assert(sizeof(EffectOutStatus) == 0x10, "EffectOutStatus is an invalid size"); + struct UpdateDataHeader { UpdateDataHeader() {} @@ -174,10 +221,12 @@ public: private: class VoiceState; + class EffectState; AudioRendererParameter worker_params; Kernel::SharedPtr buffer_event; std::vector voices; + std::vector effects; std::unique_ptr audio_out; AudioCore::StreamPtr stream; }; From 2534af040ef42107aeeff16b21df2c488121b3d6 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Sun, 7 Oct 2018 14:19:55 +1100 Subject: [PATCH 2/4] Fixed missing return Softlock explanation: after effects are initialized in smo, nothing actually changes the state. It expects the state to always be initialized. With the previous testing, updating the states much like how we handle the memory pools continue to have the softlock(which is why I said it probably wasn't effects) after further examination it seems like effects need to be initialized but the state remains unchanged until further notice. For now, assertions are added for the aux buffers to see if they update, unable to check as I haven't gotten smo to actually update them yet. --- src/audio_core/audio_renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp index 9b7970d421..5d2feb1b97 100644 --- a/src/audio_core/audio_renderer.cpp +++ b/src/audio_core/audio_renderer.cpp @@ -58,7 +58,7 @@ public: } const EffectInStatus& GetInfo() const { - info; + return info; } EffectInStatus& Info() { From ceef334c1cc2c55def468a1f83474ba8d4a3884d Mon Sep 17 00:00:00 2001 From: David Marcec Date: Sun, 7 Oct 2018 14:25:39 +1100 Subject: [PATCH 3/4] Fixups for softlock --- src/audio_core/audio_renderer.cpp | 11 ++++++----- src/audio_core/audio_renderer.h | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp index 5d2feb1b97..23e5d3f100 100644 --- a/src/audio_core/audio_renderer.cpp +++ b/src/audio_core/audio_renderer.cpp @@ -30,7 +30,7 @@ public: return info; } - VoiceInfo& Info() { + VoiceInfo& GetInfo() { return info; } @@ -61,7 +61,7 @@ public: return info; } - EffectInStatus& Info() { + EffectInStatus& GetInfo() { return info; } @@ -120,7 +120,7 @@ std::vector AudioRenderer::UpdateAudioRenderer(const std::vector& input_ std::size_t voice_offset{sizeof(UpdateDataHeader) + config.behavior_size + config.memory_pools_size + config.voice_resource_size}; for (auto& voice : voices) { - std::memcpy(&voice.Info(), input_params.data() + voice_offset, sizeof(VoiceInfo)); + std::memcpy(&voice.GetInfo(), input_params.data() + voice_offset, sizeof(VoiceInfo)); voice_offset += sizeof(VoiceInfo); } @@ -128,7 +128,7 @@ std::vector AudioRenderer::UpdateAudioRenderer(const std::vector& input_ config.memory_pools_size + config.voice_resource_size + config.voices_size}; for (auto& effect : effects) { - std::memcpy(&effect.Info(), input_params.data() + effect_offset, sizeof(EffectInStatus)); + std::memcpy(&effect.GetInfo(), input_params.data() + effect_offset, sizeof(EffectInStatus)); effect_offset += sizeof(EffectInStatus); } @@ -285,7 +285,8 @@ void AudioRenderer::VoiceState::RefreshBuffer() { break; } - samples = Interpolate(interp_state, std::move(samples), Info().sample_rate, STREAM_SAMPLE_RATE); + samples = + Interpolate(interp_state, std::move(samples), GetInfo().sample_rate, STREAM_SAMPLE_RATE); is_refresh_pending = false; } diff --git a/src/audio_core/audio_renderer.h b/src/audio_core/audio_renderer.h index a2caeb118b..4662c87225 100644 --- a/src/audio_core/audio_renderer.h +++ b/src/audio_core/audio_renderer.h @@ -220,8 +220,8 @@ public: Stream::State GetStreamState() const; private: - class VoiceState; class EffectState; + class VoiceState; AudioRendererParameter worker_params; Kernel::SharedPtr buffer_event; From a47c1c77e6dad8ebd4dfc49d76ef39b605a1ef69 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Tue, 9 Oct 2018 11:20:54 +1100 Subject: [PATCH 4/4] EffectOutStatus padding is now in hex --- src/audio_core/audio_renderer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio_core/audio_renderer.h b/src/audio_core/audio_renderer.h index 4662c87225..046417da34 100644 --- a/src/audio_core/audio_renderer.h +++ b/src/audio_core/audio_renderer.h @@ -171,7 +171,7 @@ static_assert(sizeof(EffectInStatus) == 0xc0, "EffectInStatus is an invalid size struct EffectOutStatus { EffectStatus state; - INSERT_PADDING_BYTES(15); + INSERT_PADDING_BYTES(0xf); }; static_assert(sizeof(EffectOutStatus) == 0x10, "EffectOutStatus is an invalid size");