mirror of
https://git.eden-emu.dev/archive/citron
synced 2026-03-24 10:29:35 -04:00
feat: REV15 audio renderer + HID fix (v0.8.0)
Complete SDK15 audio implementation with native float biquads. Fixes TotK 1.4.2 and BotW 1.8.2 boot loops. - Add REV15 float biquad filter support - Implement VoiceInParameterV2 (0x188 bytes) - Add SplitterDestinationV2b with biquad filters - Fix HID sampling number (double state value) - Add AudioSnoopManager and AudioSystemManager - Implement FinalOutputRecorder system - Add FFT and loudness calculator (ITU-R BS.1770) - Add full Limiter effect Resolves boot loops and controller detection in SDK20 games. Signed-off-by: Zephyron <zephyron@citron-emu.org>
This commit is contained in:
128
src/audio_core/audio_system_manager.cpp
Normal file
128
src/audio_core/audio_system_manager.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "audio_core/audio_system_manager.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/audio/errors.h"
|
||||
|
||||
namespace AudioCore {
|
||||
|
||||
AudioSystemManager::AudioSystemManager(Core::System& system_) : system{system_} {}
|
||||
AudioSystemManager::~AudioSystemManager() = default;
|
||||
|
||||
Result AudioSystemManager::RegisterAppletResourceUserId(u64 applet_resource_user_id) {
|
||||
std::scoped_lock lock{mutex};
|
||||
|
||||
if (registered_count >= MaxAppletResourceUserIds) {
|
||||
LOG_ERROR(Service_Audio, "Maximum applet resource user IDs registered");
|
||||
return Service::Audio::ResultInvalidHandle;
|
||||
}
|
||||
|
||||
// Check if already registered
|
||||
for (size_t i = 0; i < registered_count; i++) {
|
||||
if (registered_ids[i] == applet_resource_user_id) {
|
||||
return ResultSuccess; // Already registered
|
||||
}
|
||||
}
|
||||
|
||||
registered_ids[registered_count++] = applet_resource_user_id;
|
||||
LOG_DEBUG(Service_Audio, "Registered applet resource user ID: {}", applet_resource_user_id);
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result AudioSystemManager::UnregisterAppletResourceUserId(u64 applet_resource_user_id) {
|
||||
std::scoped_lock lock{mutex};
|
||||
|
||||
for (size_t i = 0; i < registered_count; i++) {
|
||||
if (registered_ids[i] == applet_resource_user_id) {
|
||||
// Remove by shifting remaining elements
|
||||
for (size_t j = i; j < registered_count - 1; j++) {
|
||||
registered_ids[j] = registered_ids[j + 1];
|
||||
}
|
||||
registered_count--;
|
||||
LOG_DEBUG(Service_Audio, "Unregistered applet resource user ID: {}",
|
||||
applet_resource_user_id);
|
||||
return ResultSuccess;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_WARNING(Service_Audio, "Applet resource user ID not found: {}", applet_resource_user_id);
|
||||
return Service::Audio::ResultInvalidHandle;
|
||||
}
|
||||
|
||||
Result AudioSystemManager::RequestSuspendAudio(u64 applet_resource_user_id) {
|
||||
std::scoped_lock lock{mutex};
|
||||
|
||||
LOG_DEBUG(Service_Audio, "Suspending audio for applet resource user ID: {}",
|
||||
applet_resource_user_id);
|
||||
audio_suspended = true;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result AudioSystemManager::RequestResumeAudio(u64 applet_resource_user_id) {
|
||||
std::scoped_lock lock{mutex};
|
||||
|
||||
LOG_DEBUG(Service_Audio, "Resuming audio for applet resource user ID: {}",
|
||||
applet_resource_user_id);
|
||||
audio_suspended = false;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result AudioSystemManager::GetAudioInputProcessMasterVolume(f32& volume) {
|
||||
std::scoped_lock lock{mutex};
|
||||
volume = input_master_volume;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result AudioSystemManager::SetAudioInputProcessMasterVolume(f32 volume) {
|
||||
std::scoped_lock lock{mutex};
|
||||
input_master_volume = std::clamp(volume, 0.0f, 1.0f);
|
||||
LOG_DEBUG(Service_Audio, "Set audio input master volume: {}", input_master_volume);
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result AudioSystemManager::GetAudioOutputProcessMasterVolume(f32& volume) {
|
||||
std::scoped_lock lock{mutex};
|
||||
volume = output_master_volume;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result AudioSystemManager::SetAudioOutputProcessMasterVolume(f32 volume) {
|
||||
std::scoped_lock lock{mutex};
|
||||
output_master_volume = std::clamp(volume, 0.0f, 1.0f);
|
||||
LOG_DEBUG(Service_Audio, "Set audio output master volume: {}", output_master_volume);
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result AudioSystemManager::GetAudioOutputProcessRecordVolume(f32& volume) {
|
||||
std::scoped_lock lock{mutex};
|
||||
volume = output_record_volume;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result AudioSystemManager::SetAudioOutputProcessRecordVolume(f32 volume) {
|
||||
std::scoped_lock lock{mutex};
|
||||
output_record_volume = std::clamp(volume, 0.0f, 1.0f);
|
||||
LOG_DEBUG(Service_Audio, "Set audio output record volume: {}", output_record_volume);
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result AudioSystemManager::RequestSuspendAudioForDebug() {
|
||||
std::scoped_lock lock{mutex};
|
||||
LOG_DEBUG(Service_Audio, "Suspending audio for debug");
|
||||
debug_suspended = true;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result AudioSystemManager::RequestResumeAudioForDebug() {
|
||||
std::scoped_lock lock{mutex};
|
||||
LOG_DEBUG(Service_Audio, "Resuming audio for debug");
|
||||
debug_suspended = false;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
} // namespace AudioCore
|
||||
Reference in New Issue
Block a user