diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp
index 6f0ff953a39e81ab5e8c30119252c2891963fa11..23e5d3f100a6623ebda47e5dbfdf3af0ce1fadc2 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;
     }
 
@@ -51,9 +51,30 @@ private:
     VoiceInfo info{};
 };
 
+class AudioRenderer::EffectState {
+public:
+    const EffectOutStatus& GetOutStatus() const {
+        return out_status;
+    }
+
+    const EffectInStatus& GetInfo() const {
+        return info;
+    }
+
+    EffectInStatus& GetInfo() {
+        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.GetInfo(), 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.GetInfo(), 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;
 }
 
@@ -244,11 +285,29 @@ 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;
 }
 
+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));
 }
diff --git a/src/audio_core/audio_renderer.h b/src/audio_core/audio_renderer.h
index dfef89e1d05000adb1df8f5f5a484d9236c92104..046417da34dcd44854a2b68e60653bc39efc1df7 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<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(0xf);
+};
+static_assert(sizeof(EffectOutStatus) == 0x10, "EffectOutStatus is an invalid size");
+
 struct UpdateDataHeader {
     UpdateDataHeader() {}
 
@@ -173,11 +220,13 @@ public:
     Stream::State GetStreamState() const;
 
 private:
+    class EffectState;
     class VoiceState;
 
     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;
 };