diff options
| author | 2018-10-07 14:14:09 +1100 | |
|---|---|---|
| committer | 2018-10-07 14:14:09 +1100 | |
| commit | 2de52e3af65e71df8a1ef00c9bcfcaa9f67330c3 (patch) | |
| tree | 9b6e8edf522ccd2b29bcfa26bd357ffa632e29d2 | |
| parent | Merge pull request #1452 from FearlessTobi/port-4313 (diff) | |
| download | yuzu-2de52e3af65e71df8a1ef00c9bcfcaa9f67330c3.tar.gz yuzu-2de52e3af65e71df8a1ef00c9bcfcaa9f67330c3.tar.xz yuzu-2de52e3af65e71df8a1ef00c9bcfcaa9f67330c3.zip | |
Fixed smo softlock
| -rw-r--r-- | src/audio_core/audio_renderer.cpp | 84 | ||||
| -rw-r--r-- | 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 6f0ff953a..9b7970d42 100644 --- a/src/audio_core/audio_renderer.cpp +++ b/src/audio_core/audio_renderer.cpp | |||
| @@ -51,9 +51,30 @@ private: | |||
| 51 | VoiceInfo info{}; | 51 | VoiceInfo info{}; |
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | class AudioRenderer::EffectState { | ||
| 55 | public: | ||
| 56 | const EffectOutStatus& GetOutStatus() const { | ||
| 57 | return out_status; | ||
| 58 | } | ||
| 59 | |||
| 60 | const EffectInStatus& GetInfo() const { | ||
| 61 | info; | ||
| 62 | } | ||
| 63 | |||
| 64 | EffectInStatus& Info() { | ||
| 65 | return info; | ||
| 66 | } | ||
| 67 | |||
| 68 | void UpdateState(); | ||
| 69 | |||
| 70 | private: | ||
| 71 | EffectOutStatus out_status{}; | ||
| 72 | EffectInStatus info{}; | ||
| 73 | }; | ||
| 54 | AudioRenderer::AudioRenderer(AudioRendererParameter params, | 74 | AudioRenderer::AudioRenderer(AudioRendererParameter params, |
| 55 | Kernel::SharedPtr<Kernel::Event> buffer_event) | 75 | Kernel::SharedPtr<Kernel::Event> buffer_event) |
| 56 | : worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count) { | 76 | : worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count), |
| 77 | effects(params.effect_count) { | ||
| 57 | 78 | ||
| 58 | audio_out = std::make_unique<AudioCore::AudioOut>(); | 79 | audio_out = std::make_unique<AudioCore::AudioOut>(); |
| 59 | stream = audio_out->OpenStream(STREAM_SAMPLE_RATE, STREAM_NUM_CHANNELS, "AudioRenderer", | 80 | stream = audio_out->OpenStream(STREAM_SAMPLE_RATE, STREAM_NUM_CHANNELS, "AudioRenderer", |
| @@ -96,11 +117,29 @@ std::vector<u8> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_ | |||
| 96 | memory_pool_count * sizeof(MemoryPoolInfo)); | 117 | memory_pool_count * sizeof(MemoryPoolInfo)); |
| 97 | 118 | ||
| 98 | // Copy VoiceInfo structs | 119 | // Copy VoiceInfo structs |
| 99 | std::size_t offset{sizeof(UpdateDataHeader) + config.behavior_size + config.memory_pools_size + | 120 | std::size_t voice_offset{sizeof(UpdateDataHeader) + config.behavior_size + |
| 100 | config.voice_resource_size}; | 121 | config.memory_pools_size + config.voice_resource_size}; |
| 101 | for (auto& voice : voices) { | 122 | for (auto& voice : voices) { |
| 102 | std::memcpy(&voice.Info(), input_params.data() + offset, sizeof(VoiceInfo)); | 123 | std::memcpy(&voice.Info(), input_params.data() + voice_offset, sizeof(VoiceInfo)); |
| 103 | offset += sizeof(VoiceInfo); | 124 | voice_offset += sizeof(VoiceInfo); |
| 125 | } | ||
| 126 | |||
| 127 | std::size_t effect_offset{sizeof(UpdateDataHeader) + config.behavior_size + | ||
| 128 | config.memory_pools_size + config.voice_resource_size + | ||
| 129 | config.voices_size}; | ||
| 130 | for (auto& effect : effects) { | ||
| 131 | std::memcpy(&effect.Info(), input_params.data() + effect_offset, sizeof(EffectInStatus)); | ||
| 132 | effect_offset += sizeof(EffectInStatus); | ||
| 133 | } | ||
| 134 | |||
| 135 | // Update memory pool state | ||
| 136 | std::vector<MemoryPoolEntry> memory_pool(memory_pool_count); | ||
| 137 | for (std::size_t index = 0; index < memory_pool.size(); ++index) { | ||
| 138 | if (mem_pool_info[index].pool_state == MemoryPoolStates::RequestAttach) { | ||
| 139 | memory_pool[index].state = MemoryPoolStates::Attached; | ||
| 140 | } else if (mem_pool_info[index].pool_state == MemoryPoolStates::RequestDetach) { | ||
| 141 | memory_pool[index].state = MemoryPoolStates::Detached; | ||
| 142 | } | ||
| 104 | } | 143 | } |
| 105 | 144 | ||
| 106 | // Update voices | 145 | // Update voices |
| @@ -114,14 +153,8 @@ std::vector<u8> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_ | |||
| 114 | } | 153 | } |
| 115 | } | 154 | } |
| 116 | 155 | ||
| 117 | // Update memory pool state | 156 | for (auto& effect : effects) { |
| 118 | std::vector<MemoryPoolEntry> memory_pool(memory_pool_count); | 157 | effect.UpdateState(); |
| 119 | for (std::size_t index = 0; index < memory_pool.size(); ++index) { | ||
| 120 | if (mem_pool_info[index].pool_state == MemoryPoolStates::RequestAttach) { | ||
| 121 | memory_pool[index].state = MemoryPoolStates::Attached; | ||
| 122 | } else if (mem_pool_info[index].pool_state == MemoryPoolStates::RequestDetach) { | ||
| 123 | memory_pool[index].state = MemoryPoolStates::Detached; | ||
| 124 | } | ||
| 125 | } | 158 | } |
| 126 | 159 | ||
| 127 | // Release previous buffers and queue next ones for playback | 160 | // Release previous buffers and queue next ones for playback |
| @@ -144,6 +177,14 @@ std::vector<u8> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_ | |||
| 144 | voice_out_status_offset += sizeof(VoiceOutStatus); | 177 | voice_out_status_offset += sizeof(VoiceOutStatus); |
| 145 | } | 178 | } |
| 146 | 179 | ||
| 180 | std::size_t effect_out_status_offset{ | ||
| 181 | sizeof(UpdateDataHeader) + response_data.memory_pools_size + response_data.voices_size + | ||
| 182 | response_data.voice_resource_size}; | ||
| 183 | for (const auto& effect : effects) { | ||
| 184 | std::memcpy(output_params.data() + effect_out_status_offset, &effect.GetOutStatus(), | ||
| 185 | sizeof(EffectOutStatus)); | ||
| 186 | effect_out_status_offset += sizeof(EffectOutStatus); | ||
| 187 | } | ||
| 147 | return output_params; | 188 | return output_params; |
| 148 | } | 189 | } |
| 149 | 190 | ||
| @@ -249,6 +290,23 @@ void AudioRenderer::VoiceState::RefreshBuffer() { | |||
| 249 | is_refresh_pending = false; | 290 | is_refresh_pending = false; |
| 250 | } | 291 | } |
| 251 | 292 | ||
| 293 | void AudioRenderer::EffectState::UpdateState() { | ||
| 294 | if (info.is_new) { | ||
| 295 | out_status.state = EffectStatus::New; | ||
| 296 | } else { | ||
| 297 | if (info.type == Effect::Aux) { | ||
| 298 | ASSERT_MSG(Memory::Read32(info.aux_info.return_buffer_info) == 0, | ||
| 299 | "Aux buffers tried to update"); | ||
| 300 | ASSERT_MSG(Memory::Read32(info.aux_info.send_buffer_info) == 0, | ||
| 301 | "Aux buffers tried to update"); | ||
| 302 | ASSERT_MSG(Memory::Read32(info.aux_info.return_buffer_base) == 0, | ||
| 303 | "Aux buffers tried to update"); | ||
| 304 | ASSERT_MSG(Memory::Read32(info.aux_info.send_buffer_base) == 0, | ||
| 305 | "Aux buffers tried to update"); | ||
| 306 | } | ||
| 307 | } | ||
| 308 | } | ||
| 309 | |||
| 252 | static constexpr s16 ClampToS16(s32 value) { | 310 | static constexpr s16 ClampToS16(s32 value) { |
| 253 | return static_cast<s16>(std::clamp(value, -32768, 32767)); | 311 | return static_cast<s16>(std::clamp(value, -32768, 32767)); |
| 254 | } | 312 | } |
diff --git a/src/audio_core/audio_renderer.h b/src/audio_core/audio_renderer.h index dfef89e1d..a2caeb118 100644 --- a/src/audio_core/audio_renderer.h +++ b/src/audio_core/audio_renderer.h | |||
| @@ -28,6 +28,16 @@ enum class PlayState : u8 { | |||
| 28 | Paused = 2, | 28 | Paused = 2, |
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | enum class Effect : u8 { | ||
| 32 | None = 0, | ||
| 33 | Aux = 2, | ||
| 34 | }; | ||
| 35 | |||
| 36 | enum class EffectStatus : u8 { | ||
| 37 | None = 0, | ||
| 38 | New = 1, | ||
| 39 | }; | ||
| 40 | |||
| 31 | struct AudioRendererParameter { | 41 | struct AudioRendererParameter { |
| 32 | u32_le sample_rate; | 42 | u32_le sample_rate; |
| 33 | u32_le sample_count; | 43 | u32_le sample_count; |
| @@ -128,6 +138,43 @@ struct VoiceOutStatus { | |||
| 128 | }; | 138 | }; |
| 129 | static_assert(sizeof(VoiceOutStatus) == 0x10, "VoiceOutStatus has wrong size"); | 139 | static_assert(sizeof(VoiceOutStatus) == 0x10, "VoiceOutStatus has wrong size"); |
| 130 | 140 | ||
| 141 | struct AuxInfo { | ||
| 142 | std::array<u8, 24> input_mix_buffers; | ||
| 143 | std::array<u8, 24> output_mix_buffers; | ||
| 144 | u32_le mix_buffer_count; | ||
| 145 | u32_le sample_rate; // Stored in the aux buffer currently | ||
| 146 | u32_le sampe_count; | ||
| 147 | u64_le send_buffer_info; | ||
| 148 | u64_le send_buffer_base; | ||
| 149 | |||
| 150 | u64_le return_buffer_info; | ||
| 151 | u64_le return_buffer_base; | ||
| 152 | }; | ||
| 153 | static_assert(sizeof(AuxInfo) == 0x60, "AuxInfo is an invalid size"); | ||
| 154 | |||
| 155 | struct EffectInStatus { | ||
| 156 | Effect type; | ||
| 157 | u8 is_new; | ||
| 158 | u8 is_enabled; | ||
| 159 | INSERT_PADDING_BYTES(1); | ||
| 160 | u32_le mix_id; | ||
| 161 | u64_le buffer_base; | ||
| 162 | u64_le buffer_sz; | ||
| 163 | s32_le priority; | ||
| 164 | INSERT_PADDING_BYTES(4); | ||
| 165 | union { | ||
| 166 | std::array<u8, 0xa0> raw; | ||
| 167 | AuxInfo aux_info; | ||
| 168 | }; | ||
| 169 | }; | ||
| 170 | static_assert(sizeof(EffectInStatus) == 0xc0, "EffectInStatus is an invalid size"); | ||
| 171 | |||
| 172 | struct EffectOutStatus { | ||
| 173 | EffectStatus state; | ||
| 174 | INSERT_PADDING_BYTES(15); | ||
| 175 | }; | ||
| 176 | static_assert(sizeof(EffectOutStatus) == 0x10, "EffectOutStatus is an invalid size"); | ||
| 177 | |||
| 131 | struct UpdateDataHeader { | 178 | struct UpdateDataHeader { |
| 132 | UpdateDataHeader() {} | 179 | UpdateDataHeader() {} |
| 133 | 180 | ||
| @@ -174,10 +221,12 @@ public: | |||
| 174 | 221 | ||
| 175 | private: | 222 | private: |
| 176 | class VoiceState; | 223 | class VoiceState; |
| 224 | class EffectState; | ||
| 177 | 225 | ||
| 178 | AudioRendererParameter worker_params; | 226 | AudioRendererParameter worker_params; |
| 179 | Kernel::SharedPtr<Kernel::Event> buffer_event; | 227 | Kernel::SharedPtr<Kernel::Event> buffer_event; |
| 180 | std::vector<VoiceState> voices; | 228 | std::vector<VoiceState> voices; |
| 229 | std::vector<EffectState> effects; | ||
| 181 | std::unique_ptr<AudioOut> audio_out; | 230 | std::unique_ptr<AudioOut> audio_out; |
| 182 | AudioCore::StreamPtr stream; | 231 | AudioCore::StreamPtr stream; |
| 183 | }; | 232 | }; |