summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2018-10-09 16:56:11 -0400
committerGravatar GitHub2018-10-09 16:56:11 -0400
commit6aab309e4198fe6952ca4e10775e579f2a0d9848 (patch)
treee13d73ab12e7d84b57132b788de3aa9cc0f8ef7d /src
parentMerge pull request #1423 from DarkLordZach/romfs-file-exts (diff)
parentEffectOutStatus padding is now in hex (diff)
downloadyuzu-6aab309e4198fe6952ca4e10775e579f2a0d9848.tar.gz
yuzu-6aab309e4198fe6952ca4e10775e579f2a0d9848.tar.xz
yuzu-6aab309e4198fe6952ca4e10775e579f2a0d9848.zip
Merge pull request #1455 from ogniK5377/smo-softlockfix
Fixed smo softlock due to incorrect effect state updating
Diffstat (limited to 'src')
-rw-r--r--src/audio_core/audio_renderer.cpp89
-rw-r--r--src/audio_core/audio_renderer.h49
2 files changed, 123 insertions, 15 deletions
diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp
index 6f0ff953a..23e5d3f10 100644
--- a/src/audio_core/audio_renderer.cpp
+++ b/src/audio_core/audio_renderer.cpp
@@ -30,7 +30,7 @@ public:
30 return info; 30 return info;
31 } 31 }
32 32
33 VoiceInfo& Info() { 33 VoiceInfo& GetInfo() {
34 return info; 34 return info;
35 } 35 }
36 36
@@ -51,9 +51,30 @@ private:
51 VoiceInfo info{}; 51 VoiceInfo info{};
52}; 52};
53 53
54class AudioRenderer::EffectState {
55public:
56 const EffectOutStatus& GetOutStatus() const {
57 return out_status;
58 }
59
60 const EffectInStatus& GetInfo() const {
61 return info;
62 }
63
64 EffectInStatus& GetInfo() {
65 return info;
66 }
67
68 void UpdateState();
69
70private:
71 EffectOutStatus out_status{};
72 EffectInStatus info{};
73};
54AudioRenderer::AudioRenderer(AudioRendererParameter params, 74AudioRenderer::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.GetInfo(), 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.GetInfo(), 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
@@ -244,11 +285,29 @@ void AudioRenderer::VoiceState::RefreshBuffer() {
244 break; 285 break;
245 } 286 }
246 287
247 samples = Interpolate(interp_state, std::move(samples), Info().sample_rate, STREAM_SAMPLE_RATE); 288 samples =
289 Interpolate(interp_state, std::move(samples), GetInfo().sample_rate, STREAM_SAMPLE_RATE);
248 290
249 is_refresh_pending = false; 291 is_refresh_pending = false;
250} 292}
251 293
294void AudioRenderer::EffectState::UpdateState() {
295 if (info.is_new) {
296 out_status.state = EffectStatus::New;
297 } else {
298 if (info.type == Effect::Aux) {
299 ASSERT_MSG(Memory::Read32(info.aux_info.return_buffer_info) == 0,
300 "Aux buffers tried to update");
301 ASSERT_MSG(Memory::Read32(info.aux_info.send_buffer_info) == 0,
302 "Aux buffers tried to update");
303 ASSERT_MSG(Memory::Read32(info.aux_info.return_buffer_base) == 0,
304 "Aux buffers tried to update");
305 ASSERT_MSG(Memory::Read32(info.aux_info.send_buffer_base) == 0,
306 "Aux buffers tried to update");
307 }
308 }
309}
310
252static constexpr s16 ClampToS16(s32 value) { 311static constexpr s16 ClampToS16(s32 value) {
253 return static_cast<s16>(std::clamp(value, -32768, 32767)); 312 return static_cast<s16>(std::clamp(value, -32768, 32767));
254} 313}
diff --git a/src/audio_core/audio_renderer.h b/src/audio_core/audio_renderer.h
index dfef89e1d..046417da3 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
31enum class Effect : u8 {
32 None = 0,
33 Aux = 2,
34};
35
36enum class EffectStatus : u8 {
37 None = 0,
38 New = 1,
39};
40
31struct AudioRendererParameter { 41struct 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};
129static_assert(sizeof(VoiceOutStatus) == 0x10, "VoiceOutStatus has wrong size"); 139static_assert(sizeof(VoiceOutStatus) == 0x10, "VoiceOutStatus has wrong size");
130 140
141struct 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};
153static_assert(sizeof(AuxInfo) == 0x60, "AuxInfo is an invalid size");
154
155struct 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};
170static_assert(sizeof(EffectInStatus) == 0xc0, "EffectInStatus is an invalid size");
171
172struct EffectOutStatus {
173 EffectStatus state;
174 INSERT_PADDING_BYTES(0xf);
175};
176static_assert(sizeof(EffectOutStatus) == 0x10, "EffectOutStatus is an invalid size");
177
131struct UpdateDataHeader { 178struct UpdateDataHeader {
132 UpdateDataHeader() {} 179 UpdateDataHeader() {}
133 180
@@ -173,11 +220,13 @@ public:
173 Stream::State GetStreamState() const; 220 Stream::State GetStreamState() const;
174 221
175private: 222private:
223 class EffectState;
176 class VoiceState; 224 class VoiceState;
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};