summaryrefslogtreecommitdiffstats
path: root/src/audio_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio_core')
-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:
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 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 {
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;
};