Fixed smo softlock
This commit is contained in:
		| @@ -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<Kernel::Event> 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<AudioCore::AudioOut>(); | ||||
|     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_ | ||||
|                 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<MemoryPoolEntry> 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<u8> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_ | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Update memory pool state | ||||
|     std::vector<MemoryPoolEntry> 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<u8> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& 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<s16>(std::clamp(value, -32768, 32767)); | ||||
| } | ||||
|   | ||||
| @@ -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<u8, 24> input_mix_buffers; | ||||
|     std::array<u8, 24> 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<u8, 0xa0> 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<Kernel::Event> buffer_event; | ||||
|     std::vector<VoiceState> voices; | ||||
|     std::vector<EffectState> effects; | ||||
|     std::unique_ptr<AudioOut> audio_out; | ||||
|     AudioCore::StreamPtr stream; | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user