mirror of
https://git.citron-emu.org/citron/emulator
synced 2025-12-19 10:43:33 +00:00
revert: af223e445f && 5ed7df1e68
- Needs To Be A Branch Signed-off-by: Zephyron <zephyron@citron-emu.org>
This commit is contained in:
@@ -125,13 +125,7 @@ void AudioRenderer::CreateSinkStreams() {
|
||||
std::string name{fmt::format("ADSP_RenderStream-{}", i)};
|
||||
streams[i] =
|
||||
sink.AcquireSinkStream(system, channels, name, ::AudioCore::Sink::StreamType::Render);
|
||||
|
||||
if (streams[i]) {
|
||||
streams[i]->SetRingSize(4);
|
||||
LOG_INFO(Service_Audio, "Created sink stream {} successfully", i);
|
||||
} else {
|
||||
LOG_ERROR(Service_Audio, "Failed to create sink stream {} - audio may be disabled", i);
|
||||
}
|
||||
streams[i]->SetRingSize(4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,12 +172,6 @@ void AudioRenderer::Main(std::stop_token stop_token) {
|
||||
|
||||
// Check this buffer is valid, as it may not be used.
|
||||
if (command_buffer.buffer != 0) {
|
||||
// Check if stream is valid before using it
|
||||
if (!streams[index]) {
|
||||
LOG_WARNING(Service_Audio, "Stream {} is null, skipping audio processing", index);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If there are no remaining commands (from the previous list),
|
||||
// this is a new command list, initialize it.
|
||||
if (command_buffer.remaining_command_count == 0) {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
@@ -14,7 +13,7 @@
|
||||
#include "common/polyfill_ranges.h"
|
||||
|
||||
namespace AudioCore {
|
||||
constexpr u32 CurrentRevision = 15;
|
||||
constexpr u32 CurrentRevision = 11;
|
||||
|
||||
enum class SupportTags {
|
||||
CommandProcessingTimeEstimatorVersion4,
|
||||
@@ -45,21 +44,6 @@ enum class SupportTags {
|
||||
DelayChannelMappingChange,
|
||||
ReverbChannelMappingChange,
|
||||
I3dl2ReverbChannelMappingChange,
|
||||
SplitterPrevVolumeResetSupported,
|
||||
// REV 14 features
|
||||
AudioRendererProcessingTimeLimit65Percent,
|
||||
AudioRendererProcessingTimeLimit60Percent,
|
||||
// REV 15 features
|
||||
AudioRendererProcessingTimeLimit55Percent,
|
||||
AudioRendererProcessingTimeLimit50Percent,
|
||||
VoiceChannelResourceLimit,
|
||||
EffectProcessingVersion3,
|
||||
AudioRendererRenderingTimeLimit,
|
||||
AudioRendererVoiceDropParameter,
|
||||
AudioRendererExecutionMode,
|
||||
AudioRendererRenderingDevice,
|
||||
AudioRendererExclusiveControlLeakageCheck,
|
||||
AudioRendererElapsedFrameCount,
|
||||
|
||||
// Not a real tag, just here to get the count.
|
||||
Size
|
||||
@@ -70,7 +54,6 @@ constexpr u32 GetRevisionNum(u32 user_revision) {
|
||||
user_revision -= Common::MakeMagic('R', 'E', 'V', '0');
|
||||
user_revision >>= 24;
|
||||
}
|
||||
|
||||
return user_revision;
|
||||
};
|
||||
|
||||
@@ -104,21 +87,6 @@ constexpr bool CheckFeatureSupported(SupportTags tag, u32 user_revision) {
|
||||
{SupportTags::DelayChannelMappingChange, 11},
|
||||
{SupportTags::ReverbChannelMappingChange, 11},
|
||||
{SupportTags::I3dl2ReverbChannelMappingChange, 11},
|
||||
{SupportTags::SplitterPrevVolumeResetSupported, 13},
|
||||
// REV 14 features
|
||||
{SupportTags::AudioRendererProcessingTimeLimit65Percent, 14},
|
||||
{SupportTags::AudioRendererProcessingTimeLimit60Percent, 14},
|
||||
// REV 15 features
|
||||
{SupportTags::AudioRendererProcessingTimeLimit55Percent, 15},
|
||||
{SupportTags::AudioRendererProcessingTimeLimit50Percent, 15},
|
||||
{SupportTags::VoiceChannelResourceLimit, 15},
|
||||
{SupportTags::EffectProcessingVersion3, 15},
|
||||
{SupportTags::AudioRendererRenderingTimeLimit, 15},
|
||||
{SupportTags::AudioRendererVoiceDropParameter, 15},
|
||||
{SupportTags::AudioRendererExecutionMode, 15},
|
||||
{SupportTags::AudioRendererRenderingDevice, 15},
|
||||
{SupportTags::AudioRendererExclusiveControlLeakageCheck, 15},
|
||||
{SupportTags::AudioRendererElapsedFrameCount, 15},
|
||||
}};
|
||||
|
||||
const auto& feature =
|
||||
|
||||
@@ -190,56 +190,4 @@ bool BehaviorInfo::IsI3dl2ReverbChannelMappingChanged() const {
|
||||
return CheckFeatureSupported(SupportTags::I3dl2ReverbChannelMappingChange, user_revision);
|
||||
}
|
||||
|
||||
bool BehaviorInfo::IsSplitterPrevVolumeResetSupported() const {
|
||||
return CheckFeatureSupported(SupportTags::SplitterPrevVolumeResetSupported, user_revision);
|
||||
}
|
||||
|
||||
bool BehaviorInfo::IsAudioRendererProcessingTimeLimit65PercentSupported() const {
|
||||
return CheckFeatureSupported(SupportTags::AudioRendererProcessingTimeLimit65Percent, user_revision);
|
||||
}
|
||||
|
||||
bool BehaviorInfo::IsAudioRendererProcessingTimeLimit60PercentSupported() const {
|
||||
return CheckFeatureSupported(SupportTags::AudioRendererProcessingTimeLimit60Percent, user_revision);
|
||||
}
|
||||
|
||||
bool BehaviorInfo::IsAudioRendererProcessingTimeLimit55PercentSupported() const {
|
||||
return CheckFeatureSupported(SupportTags::AudioRendererProcessingTimeLimit55Percent, user_revision);
|
||||
}
|
||||
|
||||
bool BehaviorInfo::IsAudioRendererProcessingTimeLimit50PercentSupported() const {
|
||||
return CheckFeatureSupported(SupportTags::AudioRendererProcessingTimeLimit50Percent, user_revision);
|
||||
}
|
||||
|
||||
bool BehaviorInfo::IsVoiceChannelResourceLimitSupported() const {
|
||||
return CheckFeatureSupported(SupportTags::VoiceChannelResourceLimit, user_revision);
|
||||
}
|
||||
|
||||
bool BehaviorInfo::IsEffectProcessingVersion3Supported() const {
|
||||
return CheckFeatureSupported(SupportTags::EffectProcessingVersion3, user_revision);
|
||||
}
|
||||
|
||||
bool BehaviorInfo::IsAudioRendererRenderingTimeLimitSupported() const {
|
||||
return CheckFeatureSupported(SupportTags::AudioRendererRenderingTimeLimit, user_revision);
|
||||
}
|
||||
|
||||
bool BehaviorInfo::IsAudioRendererVoiceDropParameterSupported() const {
|
||||
return CheckFeatureSupported(SupportTags::AudioRendererVoiceDropParameter, user_revision);
|
||||
}
|
||||
|
||||
bool BehaviorInfo::IsAudioRendererExecutionModeSupported() const {
|
||||
return CheckFeatureSupported(SupportTags::AudioRendererExecutionMode, user_revision);
|
||||
}
|
||||
|
||||
bool BehaviorInfo::IsAudioRendererRenderingDeviceSupported() const {
|
||||
return CheckFeatureSupported(SupportTags::AudioRendererRenderingDevice, user_revision);
|
||||
}
|
||||
|
||||
bool BehaviorInfo::IsAudioRendererExclusiveControlLeakageCheckSupported() const {
|
||||
return CheckFeatureSupported(SupportTags::AudioRendererExclusiveControlLeakageCheck, user_revision);
|
||||
}
|
||||
|
||||
bool BehaviorInfo::IsAudioRendererElapsedFrameCountSupported() const {
|
||||
return CheckFeatureSupported(SupportTags::AudioRendererElapsedFrameCount, user_revision);
|
||||
}
|
||||
|
||||
} // namespace AudioCore::Renderer
|
||||
|
||||
@@ -361,97 +361,6 @@ public:
|
||||
*/
|
||||
bool IsI3dl2ReverbChannelMappingChanged() const;
|
||||
|
||||
/**
|
||||
* Check if explicit previous mix volume reset is supported for splitters.
|
||||
*
|
||||
* @return True if supported, otherwise false.
|
||||
*/
|
||||
bool IsSplitterPrevVolumeResetSupported() const;
|
||||
|
||||
/**
|
||||
* Check if 65% processing time limit is supported.
|
||||
*
|
||||
* @return True if supported, otherwise false.
|
||||
*/
|
||||
bool IsAudioRendererProcessingTimeLimit65PercentSupported() const;
|
||||
|
||||
/**
|
||||
* Check if 60% processing time limit is supported.
|
||||
*
|
||||
* @return True if supported, otherwise false.
|
||||
*/
|
||||
bool IsAudioRendererProcessingTimeLimit60PercentSupported() const;
|
||||
|
||||
/**
|
||||
* Check if 55% processing time limit is supported.
|
||||
*
|
||||
* @return True if supported, otherwise false.
|
||||
*/
|
||||
bool IsAudioRendererProcessingTimeLimit55PercentSupported() const;
|
||||
|
||||
/**
|
||||
* Check if 50% processing time limit is supported.
|
||||
*
|
||||
* @return True if supported, otherwise false.
|
||||
*/
|
||||
bool IsAudioRendererProcessingTimeLimit50PercentSupported() const;
|
||||
|
||||
/**
|
||||
* Check if voice channel resource limit is supported.
|
||||
*
|
||||
* @return True if supported, otherwise false.
|
||||
*/
|
||||
bool IsVoiceChannelResourceLimitSupported() const;
|
||||
|
||||
/**
|
||||
* Check if effect processing version 3 is supported.
|
||||
*
|
||||
* @return True if supported, otherwise false.
|
||||
*/
|
||||
bool IsEffectProcessingVersion3Supported() const;
|
||||
|
||||
/**
|
||||
* Check if audio renderer rendering time limit is supported.
|
||||
*
|
||||
* @return True if supported, otherwise false.
|
||||
*/
|
||||
bool IsAudioRendererRenderingTimeLimitSupported() const;
|
||||
|
||||
/**
|
||||
* Check if audio renderer voice drop parameter is supported.
|
||||
*
|
||||
* @return True if supported, otherwise false.
|
||||
*/
|
||||
bool IsAudioRendererVoiceDropParameterSupported() const;
|
||||
|
||||
/**
|
||||
* Check if audio renderer execution mode is supported.
|
||||
*
|
||||
* @return True if supported, otherwise false.
|
||||
*/
|
||||
bool IsAudioRendererExecutionModeSupported() const;
|
||||
|
||||
/**
|
||||
* Check if audio renderer rendering device is supported.
|
||||
*
|
||||
* @return True if supported, otherwise false.
|
||||
*/
|
||||
bool IsAudioRendererRenderingDeviceSupported() const;
|
||||
|
||||
/**
|
||||
* Check if audio renderer exclusive control leakage check is supported.
|
||||
*
|
||||
* @return True if supported, otherwise false.
|
||||
*/
|
||||
bool IsAudioRendererExclusiveControlLeakageCheckSupported() const;
|
||||
|
||||
/**
|
||||
* Check if audio renderer elapsed frame count is supported.
|
||||
*
|
||||
* @return True if supported, otherwise false.
|
||||
*/
|
||||
bool IsAudioRendererElapsedFrameCountSupported() const;
|
||||
|
||||
/// Host version
|
||||
u32 process_revision;
|
||||
/// User version
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <algorithm>
|
||||
#include "audio_core/common/feature_support.h"
|
||||
#include "audio_core/renderer/behavior/behavior_info.h"
|
||||
#include "audio_core/renderer/behavior/info_updater.h"
|
||||
@@ -44,15 +42,13 @@ Result InfoUpdater::UpdateVoiceChannelResources(VoiceContext& voice_context) {
|
||||
}
|
||||
}
|
||||
|
||||
auto consumed_input_size{voice_count *
|
||||
static_cast<u32>(sizeof(VoiceChannelResource::InParameter))};
|
||||
const auto consumed_input_size{voice_count *
|
||||
static_cast<u32>(sizeof(VoiceChannelResource::InParameter))};
|
||||
if (consumed_input_size != in_header->voice_resources_size) {
|
||||
LOG_ERROR(Service_Audio,
|
||||
"Consumed an incorrect voice resource size, header size={}, consumed={}",
|
||||
in_header->voice_resources_size, consumed_input_size);
|
||||
// Adjust the consumed size to match the header to prevent crashes
|
||||
consumed_input_size = in_header->voice_resources_size;
|
||||
LOG_WARNING(Service_Audio, "Adjusted voice resource consumed size to match header size");
|
||||
return Service::Audio::ResultInvalidUpdateInfo;
|
||||
}
|
||||
|
||||
input += consumed_input_size;
|
||||
@@ -65,22 +61,6 @@ Result InfoUpdater::UpdateVoices(VoiceContext& voice_context,
|
||||
const PoolMapper pool_mapper(process_handle, memory_pools, memory_pool_count,
|
||||
behaviour.IsMemoryForceMappingEnabled());
|
||||
const auto voice_count{voice_context.GetCount()};
|
||||
|
||||
// Check if we should use float biquad filters (revision 7+)
|
||||
const bool use_float_biquads = behaviour.UseBiquadFilterFloatProcessing();
|
||||
|
||||
if (use_float_biquads) {
|
||||
return UpdateVoicesFloat(voice_context, memory_pools, memory_pool_count, pool_mapper, voice_count);
|
||||
} else {
|
||||
return UpdateVoicesInt(voice_context, memory_pools, memory_pool_count, pool_mapper, voice_count);
|
||||
}
|
||||
}
|
||||
|
||||
Result InfoUpdater::UpdateVoicesInt(VoiceContext& voice_context,
|
||||
std::span<MemoryPoolInfo> memory_pools,
|
||||
const u32 memory_pool_count,
|
||||
const PoolMapper& pool_mapper,
|
||||
const u32 voice_count) {
|
||||
std::span<const VoiceInfo::InParameter> in_params{
|
||||
reinterpret_cast<const VoiceInfo::InParameter*>(input), voice_count};
|
||||
std::span<VoiceInfo::OutStatus> out_params{reinterpret_cast<VoiceInfo::OutStatus*>(output),
|
||||
@@ -103,18 +83,14 @@ Result InfoUpdater::UpdateVoicesInt(VoiceContext& voice_context,
|
||||
|
||||
auto& voice_info{voice_context.GetInfo(in_param.id)};
|
||||
|
||||
// FIX: Calculate a safe channel count to prevent out-of-bounds access.
|
||||
const u32 safe_channel_count = std::min(in_param.channel_count, static_cast<u32>(MaxChannels));
|
||||
|
||||
for (u32 channel = 0; channel < safe_channel_count; channel++) {
|
||||
for (u32 channel = 0; channel < in_param.channel_count; channel++) {
|
||||
voice_states[channel] = &voice_context.GetState(in_param.channel_resource_ids[channel]);
|
||||
}
|
||||
|
||||
if (in_param.is_new) {
|
||||
voice_info.Initialize();
|
||||
|
||||
// FIX: Use the same safe channel count for this loop.
|
||||
for (u32 channel = 0; channel < safe_channel_count; channel++) {
|
||||
for (u32 channel = 0; channel < in_param.channel_count; channel++) {
|
||||
*voice_states[channel] = {};
|
||||
}
|
||||
}
|
||||
@@ -145,138 +121,9 @@ Result InfoUpdater::UpdateVoicesInt(VoiceContext& voice_context,
|
||||
auto consumed_input_size{voice_count * static_cast<u32>(sizeof(VoiceInfo::InParameter))};
|
||||
auto consumed_output_size{voice_count * static_cast<u32>(sizeof(VoiceInfo::OutStatus))};
|
||||
if (consumed_input_size != in_header->voices_size) {
|
||||
LOG_ERROR(Service_Audio, "Consumed an incorrect voices size, header size={}, consumed={}, voice_count={}, sizeof(VoiceInfo::InParameter)={}",
|
||||
in_header->voices_size, consumed_input_size, voice_count, sizeof(VoiceInfo::InParameter));
|
||||
// Instead of returning an error, adjust the consumed size to match the header
|
||||
// This prevents the audio system from crashing due to size mismatches
|
||||
consumed_input_size = in_header->voices_size;
|
||||
LOG_WARNING(Service_Audio, "Adjusted consumed input size to match header size");
|
||||
}
|
||||
|
||||
out_header->voices_size = consumed_output_size;
|
||||
out_header->size += consumed_output_size;
|
||||
input += consumed_input_size;
|
||||
output += consumed_output_size;
|
||||
|
||||
voice_context.SetActiveCount(new_voice_count);
|
||||
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result InfoUpdater::UpdateVoicesFloat(VoiceContext& voice_context,
|
||||
std::span<MemoryPoolInfo> memory_pools,
|
||||
const u32 memory_pool_count,
|
||||
const PoolMapper& pool_mapper,
|
||||
const u32 voice_count) {
|
||||
std::span<const VoiceInfo::InParameterFloat> in_params{
|
||||
reinterpret_cast<const VoiceInfo::InParameterFloat*>(input), voice_count};
|
||||
std::span<VoiceInfo::OutStatus> out_params{reinterpret_cast<VoiceInfo::OutStatus*>(output),
|
||||
voice_count};
|
||||
|
||||
for (u32 i = 0; i < voice_count; i++) {
|
||||
auto& voice_info{voice_context.GetInfo(i)};
|
||||
voice_info.in_use = false;
|
||||
}
|
||||
|
||||
u32 new_voice_count{0};
|
||||
|
||||
for (u32 i = 0; i < voice_count; i++) {
|
||||
const auto& in_param{in_params[i]};
|
||||
std::array<VoiceState*, MaxChannels> voice_states{};
|
||||
|
||||
if (!in_param.in_use) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& voice_info{voice_context.GetInfo(in_param.id)};
|
||||
|
||||
// FIX: Calculate a safe channel count to prevent out-of-bounds access.
|
||||
const u32 safe_channel_count = std::min(in_param.channel_count, static_cast<u32>(MaxChannels));
|
||||
|
||||
for (u32 channel = 0; channel < safe_channel_count; channel++) {
|
||||
voice_states[channel] = &voice_context.GetState(in_param.channel_resource_ids[channel]);
|
||||
}
|
||||
|
||||
if (in_param.is_new) {
|
||||
voice_info.Initialize();
|
||||
|
||||
// FIX: Use the same safe channel count for this loop.
|
||||
for (u32 channel = 0; channel < safe_channel_count; channel++) {
|
||||
*voice_states[channel] = {};
|
||||
}
|
||||
}
|
||||
|
||||
// Convert float biquad parameters to integer for compatibility
|
||||
VoiceInfo::InParameter int_param{};
|
||||
int_param.id = in_param.id;
|
||||
int_param.node_id = in_param.node_id;
|
||||
int_param.is_new = in_param.is_new;
|
||||
int_param.in_use = in_param.in_use;
|
||||
int_param.play_state = in_param.play_state;
|
||||
int_param.sample_format = in_param.sample_format;
|
||||
int_param.sample_rate = in_param.sample_rate;
|
||||
int_param.priority = in_param.priority;
|
||||
int_param.sort_order = in_param.sort_order;
|
||||
int_param.channel_count = in_param.channel_count;
|
||||
int_param.pitch = in_param.pitch;
|
||||
int_param.volume = in_param.volume;
|
||||
|
||||
// Convert float biquad coefficients to integers (multiply by 32767 for 16-bit range)
|
||||
for (u32 j = 0; j < MaxBiquadFilters; j++) {
|
||||
int_param.biquads[j].enabled = in_param.biquads[j].enabled;
|
||||
for (u32 k = 0; k < 3; k++) {
|
||||
int_param.biquads[j].b[k] = static_cast<s16>(in_param.biquads[j].b[k] * 32767.0f);
|
||||
}
|
||||
for (u32 k = 0; k < 2; k++) {
|
||||
int_param.biquads[j].a[k] = static_cast<s16>(in_param.biquads[j].a[k] * 32767.0f);
|
||||
}
|
||||
}
|
||||
|
||||
int_param.wave_buffer_count = in_param.wave_buffer_count;
|
||||
int_param.wave_buffer_index = in_param.wave_buffer_index;
|
||||
int_param.src_data_address = in_param.src_data_address;
|
||||
int_param.src_data_size = in_param.src_data_size;
|
||||
int_param.mix_id = in_param.mix_id;
|
||||
int_param.splitter_id = in_param.splitter_id;
|
||||
int_param.wave_buffer_internal = in_param.wave_buffer_internal;
|
||||
int_param.channel_resource_ids = in_param.channel_resource_ids;
|
||||
int_param.clear_voice_drop = in_param.clear_voice_drop;
|
||||
int_param.flush_buffer_count = in_param.flush_buffer_count;
|
||||
int_param.flags = in_param.flags;
|
||||
int_param.src_quality = in_param.src_quality;
|
||||
|
||||
BehaviorInfo::ErrorInfo update_error{};
|
||||
voice_info.UpdateParameters(update_error, int_param, pool_mapper, behaviour);
|
||||
|
||||
if (!update_error.error_code.IsSuccess()) {
|
||||
behaviour.AppendError(update_error);
|
||||
}
|
||||
|
||||
std::array<std::array<BehaviorInfo::ErrorInfo, 2>, MaxWaveBuffers> wavebuffer_errors{};
|
||||
voice_info.UpdateWaveBuffers(wavebuffer_errors, MaxWaveBuffers * 2, int_param, voice_states,
|
||||
pool_mapper, behaviour);
|
||||
|
||||
for (auto& wavebuffer_error : wavebuffer_errors) {
|
||||
for (auto& error : wavebuffer_error) {
|
||||
if (error.error_code.IsError()) {
|
||||
behaviour.AppendError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
voice_info.WriteOutStatus(out_params[i], int_param, voice_states);
|
||||
new_voice_count += in_param.channel_count;
|
||||
}
|
||||
|
||||
auto consumed_input_size{voice_count * static_cast<u32>(sizeof(VoiceInfo::InParameterFloat))};
|
||||
auto consumed_output_size{voice_count * static_cast<u32>(sizeof(VoiceInfo::OutStatus))};
|
||||
if (consumed_input_size != in_header->voices_size) {
|
||||
LOG_ERROR(Service_Audio, "Consumed an incorrect voices size (float), header size={}, consumed={}, voice_count={}, sizeof(VoiceInfo::InParameterFloat)={}",
|
||||
in_header->voices_size, consumed_input_size, voice_count, sizeof(VoiceInfo::InParameterFloat));
|
||||
// Instead of returning an error, adjust the consumed size to match the header
|
||||
// This prevents the audio system from crashing due to size mismatches
|
||||
consumed_input_size = in_header->voices_size;
|
||||
LOG_WARNING(Service_Audio, "Adjusted consumed input size to match header size (float)");
|
||||
LOG_ERROR(Service_Audio, "Consumed an incorrect voices size, header size={}, consumed={}",
|
||||
in_header->voices_size, consumed_input_size);
|
||||
return Service::Audio::ResultInvalidUpdateInfo;
|
||||
}
|
||||
|
||||
out_header->voices_size = consumed_output_size;
|
||||
@@ -337,9 +184,7 @@ Result InfoUpdater::UpdateEffectsVersion1(EffectContext& effect_context, const b
|
||||
if (consumed_input_size != in_header->effects_size) {
|
||||
LOG_ERROR(Service_Audio, "Consumed an incorrect effects size, header size={}, consumed={}",
|
||||
in_header->effects_size, consumed_input_size);
|
||||
// Adjust the consumed size to match the header to prevent crashes
|
||||
consumed_input_size = in_header->effects_size;
|
||||
LOG_WARNING(Service_Audio, "Adjusted effects consumed size to match header size");
|
||||
return Service::Audio::ResultInvalidUpdateInfo;
|
||||
}
|
||||
|
||||
out_header->effects_size = consumed_output_size;
|
||||
@@ -394,9 +239,7 @@ Result InfoUpdater::UpdateEffectsVersion2(EffectContext& effect_context, const b
|
||||
if (consumed_input_size != in_header->effects_size) {
|
||||
LOG_ERROR(Service_Audio, "Consumed an incorrect effects size, header size={}, consumed={}",
|
||||
in_header->effects_size, consumed_input_size);
|
||||
// Adjust the consumed size to match the header to prevent crashes
|
||||
consumed_input_size = in_header->effects_size;
|
||||
LOG_WARNING(Service_Audio, "Adjusted effects consumed size to match header size");
|
||||
return Service::Audio::ResultInvalidUpdateInfo;
|
||||
}
|
||||
|
||||
out_header->effects_size = consumed_output_size;
|
||||
@@ -484,9 +327,7 @@ Result InfoUpdater::UpdateMixes(MixContext& mix_context, const u32 mix_buffer_co
|
||||
if (consumed_input_size != in_header->mix_size) {
|
||||
LOG_ERROR(Service_Audio, "Consumed an incorrect mixes size, header size={}, consumed={}",
|
||||
in_header->mix_size, consumed_input_size);
|
||||
// Adjust the consumed size to match the header to prevent crashes
|
||||
consumed_input_size = in_header->mix_size;
|
||||
LOG_WARNING(Service_Audio, "Adjusted mix consumed size to match header size");
|
||||
return Service::Audio::ResultInvalidUpdateInfo;
|
||||
}
|
||||
|
||||
input += mix_count * sizeof(MixInfo::InParameter);
|
||||
@@ -537,9 +378,9 @@ Result InfoUpdater::UpdateSinks(SinkContext& sink_context, std::span<MemoryPoolI
|
||||
}
|
||||
}
|
||||
|
||||
auto consumed_input_size{sink_count *
|
||||
static_cast<u32>(sizeof(SinkInfoBase::InParameter))};
|
||||
auto consumed_output_size{sink_count * static_cast<u32>(sizeof(SinkInfoBase::OutStatus))};
|
||||
const auto consumed_input_size{sink_count *
|
||||
static_cast<u32>(sizeof(SinkInfoBase::InParameter))};
|
||||
const auto consumed_output_size{sink_count * static_cast<u32>(sizeof(SinkInfoBase::OutStatus))};
|
||||
if (consumed_input_size != in_header->sinks_size) {
|
||||
LOG_ERROR(Service_Audio, "Consumed an incorrect sinks size, header size={}, consumed={}",
|
||||
in_header->sinks_size, consumed_input_size);
|
||||
@@ -574,10 +415,10 @@ Result InfoUpdater::UpdateMemoryPools(std::span<MemoryPoolInfo> memory_pools,
|
||||
}
|
||||
}
|
||||
|
||||
auto consumed_input_size{memory_pool_count *
|
||||
static_cast<u32>(sizeof(MemoryPoolInfo::InParameter))};
|
||||
auto consumed_output_size{memory_pool_count *
|
||||
static_cast<u32>(sizeof(MemoryPoolInfo::OutStatus))};
|
||||
const auto consumed_input_size{memory_pool_count *
|
||||
static_cast<u32>(sizeof(MemoryPoolInfo::InParameter))};
|
||||
const auto consumed_output_size{memory_pool_count *
|
||||
static_cast<u32>(sizeof(MemoryPoolInfo::OutStatus))};
|
||||
if (consumed_input_size != in_header->memory_pool_size) {
|
||||
LOG_ERROR(Service_Audio,
|
||||
"Consumed an incorrect memory pool size, header size={}, consumed={}",
|
||||
@@ -606,8 +447,8 @@ Result InfoUpdater::UpdatePerformanceBuffer(std::span<u8> performance_output,
|
||||
out_params->history_size = 0;
|
||||
}
|
||||
|
||||
auto consumed_input_size{static_cast<u32>(sizeof(PerformanceManager::InParameter))};
|
||||
auto consumed_output_size{static_cast<u32>(sizeof(PerformanceManager::OutStatus))};
|
||||
const auto consumed_input_size{static_cast<u32>(sizeof(PerformanceManager::InParameter))};
|
||||
const auto consumed_output_size{static_cast<u32>(sizeof(PerformanceManager::OutStatus))};
|
||||
if (consumed_input_size != in_header->performance_buffer_size) {
|
||||
LOG_ERROR(Service_Audio,
|
||||
"Consumed an incorrect performance size, header size={}, consumed={}",
|
||||
@@ -687,16 +528,10 @@ Result InfoUpdater::UpdateRendererInfo(const u64 elapsed_frames) {
|
||||
}
|
||||
|
||||
Result InfoUpdater::CheckConsumedSize() {
|
||||
const auto actual_input_size = CpuAddr(input) - CpuAddr(input_origin.data());
|
||||
const auto actual_output_size = CpuAddr(output) - CpuAddr(output_origin.data());
|
||||
|
||||
if (actual_input_size != expected_input_size) {
|
||||
LOG_WARNING(Service_Audio, "Input size mismatch: expected={}, actual={}", expected_input_size, actual_input_size);
|
||||
// Don't fail - just warn and continue
|
||||
}
|
||||
if (actual_output_size != expected_output_size) {
|
||||
LOG_WARNING(Service_Audio, "Output size mismatch: expected={}, actual={}", expected_output_size, actual_output_size);
|
||||
// Don't fail - just warn and continue
|
||||
if (CpuAddr(input) - CpuAddr(input_origin.data()) != expected_input_size) {
|
||||
return Service::Audio::ResultInvalidUpdateInfo;
|
||||
} else if (CpuAddr(output) - CpuAddr(output_origin.data()) != expected_output_size) {
|
||||
return Service::Audio::ResultInvalidUpdateInfo;
|
||||
}
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ class SplitterContext;
|
||||
class EffectContext;
|
||||
class MemoryPoolInfo;
|
||||
class PerformanceManager;
|
||||
class PoolMapper;
|
||||
|
||||
class InfoUpdater {
|
||||
struct UpdateDataHeader {
|
||||
@@ -66,32 +65,6 @@ public:
|
||||
Result UpdateVoices(VoiceContext& voice_context, std::span<MemoryPoolInfo> memory_pools,
|
||||
u32 memory_pool_count);
|
||||
|
||||
/**
|
||||
* Update voices with integer biquad filters.
|
||||
*
|
||||
* @param voice_context - Voice context to update.
|
||||
* @param memory_pools - Memory pools to use for these voices.
|
||||
* @param memory_pool_count - Number of memory pools.
|
||||
* @param pool_mapper - Pool mapper for memory operations.
|
||||
* @param voice_count - Number of voices to update.
|
||||
* @return Result code.
|
||||
*/
|
||||
Result UpdateVoicesInt(VoiceContext& voice_context, std::span<MemoryPoolInfo> memory_pools,
|
||||
u32 memory_pool_count, const PoolMapper& pool_mapper, u32 voice_count);
|
||||
|
||||
/**
|
||||
* Update voices with float biquad filters.
|
||||
*
|
||||
* @param voice_context - Voice context to update.
|
||||
* @param memory_pools - Memory pools to use for these voices.
|
||||
* @param memory_pool_count - Number of memory pools.
|
||||
* @param pool_mapper - Pool mapper for memory operations.
|
||||
* @param voice_count - Number of voices to update.
|
||||
* @return Result code.
|
||||
*/
|
||||
Result UpdateVoicesFloat(VoiceContext& voice_context, std::span<MemoryPoolInfo> memory_pools,
|
||||
u32 memory_pool_count, const PoolMapper& pool_mapper, u32 voice_count);
|
||||
|
||||
/**
|
||||
* Update effects.
|
||||
*
|
||||
|
||||
@@ -56,8 +56,6 @@ struct CompressorCommand : ICommand {
|
||||
CpuAddr workbuffer;
|
||||
/// Is this effect enabled?
|
||||
bool effect_enabled;
|
||||
/// Effect result state for statistics (REV 13+)
|
||||
CpuAddr result_state;
|
||||
};
|
||||
|
||||
} // namespace AudioCore::Renderer
|
||||
|
||||
@@ -50,8 +50,6 @@ public:
|
||||
/* 0x30 */ f32 out_gain;
|
||||
/* 0x34 */ ParameterState state;
|
||||
/* 0x35 */ bool makeup_gain_enabled;
|
||||
/* 0x36 */ bool statistics_enabled;
|
||||
/* 0x37 */ bool statistics_reset;
|
||||
};
|
||||
static_assert(sizeof(ParameterVersion2) <= sizeof(EffectInfoBase::InParameterVersion2),
|
||||
"CompressorInfo::ParameterVersion2 has the wrong size!");
|
||||
@@ -71,22 +69,6 @@ public:
|
||||
static_assert(sizeof(State) <= sizeof(EffectInfoBase::State),
|
||||
"CompressorInfo::State has the wrong size!");
|
||||
|
||||
struct Statistics {
|
||||
f32 maximum_mean;
|
||||
f32 minimum_gain;
|
||||
std::array<f32, MaxChannels> last_samples;
|
||||
|
||||
void Reset(u16 channel_count) {
|
||||
maximum_mean = 0.0f;
|
||||
minimum_gain = 1.0f;
|
||||
for (u16 i = 0; i < channel_count; i++) {
|
||||
last_samples[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(Statistics) <= sizeof(EffectResultState),
|
||||
"CompressorInfo::Statistics has the wrong size!");
|
||||
|
||||
/**
|
||||
* Update the info with new parameters, version 1.
|
||||
*
|
||||
|
||||
@@ -49,7 +49,7 @@ std::span<f32> SplitterDestinationData::GetMixVolumePrev() {
|
||||
return prev_mix_volumes;
|
||||
}
|
||||
|
||||
void SplitterDestinationData::Update(const InParameter& params, bool is_prev_volume_reset_supported) {
|
||||
void SplitterDestinationData::Update(const InParameter& params) {
|
||||
if (params.id != id || params.magic != GetSplitterSendDataMagic()) {
|
||||
return;
|
||||
}
|
||||
@@ -57,13 +57,9 @@ void SplitterDestinationData::Update(const InParameter& params, bool is_prev_vol
|
||||
destination_id = params.mix_id;
|
||||
mix_volumes = params.mix_volumes;
|
||||
|
||||
bool reset_prev_volume = is_prev_volume_reset_supported ? params.reset_prev_volume : (!in_use && params.in_use);
|
||||
|
||||
if (reset_prev_volume) {
|
||||
if (!in_use && params.in_use) {
|
||||
prev_mix_volumes = mix_volumes;
|
||||
need_update = false;
|
||||
} else if (in_use && params.in_use) {
|
||||
need_update = true;
|
||||
}
|
||||
|
||||
in_use = params.in_use;
|
||||
|
||||
@@ -22,7 +22,6 @@ public:
|
||||
/* 0x08 */ std::array<f32, MaxMixBuffers> mix_volumes;
|
||||
/* 0x68 */ u32 mix_id;
|
||||
/* 0x6C */ bool in_use;
|
||||
/* 0x6D */ bool reset_prev_volume;
|
||||
};
|
||||
static_assert(sizeof(InParameter) == 0x70,
|
||||
"SplitterDestinationData::InParameter has the wrong size!");
|
||||
@@ -89,9 +88,8 @@ public:
|
||||
* Update this destination.
|
||||
*
|
||||
* @param params - Input parameters to update the destination.
|
||||
* @param is_prev_volume_reset_supported - Whether explicit prev volume reset is supported.
|
||||
*/
|
||||
void Update(const InParameter& params, bool is_prev_volume_reset_supported = false);
|
||||
void Update(const InParameter& params);
|
||||
|
||||
/**
|
||||
* Mark this destination as needing its volumes updated.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <ranges>
|
||||
@@ -11,16 +10,14 @@ namespace AudioCore::Renderer {
|
||||
|
||||
VoiceState& VoiceContext::GetDspSharedState(const u32 index) {
|
||||
if (index >= dsp_states.size()) {
|
||||
LOG_CRITICAL(Service_Audio, "Attempted to access invalid voice dsp state index {:04X} (max is {})", index, dsp_states.size() > 0 ? dsp_states.size() - 1 : 0);
|
||||
return dsp_states[0];
|
||||
LOG_ERROR(Service_Audio, "Invalid voice dsp state index {:04X}", index);
|
||||
}
|
||||
return dsp_states[index];
|
||||
}
|
||||
|
||||
VoiceChannelResource& VoiceContext::GetChannelResource(const u32 index) {
|
||||
if (index >= channel_resources.size()) {
|
||||
LOG_CRITICAL(Service_Audio, "Attempted to access invalid voice channel resource index {:04X} (max is {})", index, channel_resources.size() > 0 ? channel_resources.size() - 1 : 0);
|
||||
return channel_resources[0];
|
||||
LOG_ERROR(Service_Audio, "Invalid voice channel resource index {:04X}", index);
|
||||
}
|
||||
return channel_resources[index];
|
||||
}
|
||||
@@ -48,16 +45,14 @@ VoiceInfo* VoiceContext::GetSortedInfo(const u32 index) {
|
||||
|
||||
VoiceInfo& VoiceContext::GetInfo(const u32 index) {
|
||||
if (index >= voices.size()) {
|
||||
LOG_CRITICAL(Service_Audio, "Attempted to access invalid voice info index {:04X} (max is {})", index, voices.size() > 0 ? voices.size() - 1 : 0);
|
||||
return voices[0];
|
||||
LOG_ERROR(Service_Audio, "Invalid voice info index {:04X}", index);
|
||||
}
|
||||
return voices[index];
|
||||
}
|
||||
|
||||
VoiceState& VoiceContext::GetState(const u32 index) {
|
||||
if (index >= cpu_states.size()) {
|
||||
LOG_CRITICAL(Service_Audio, "Attempted to access invalid voice cpu state index {:04X} (max is {})", index, cpu_states.size() > 0 ? cpu_states.size() - 1 : 0);
|
||||
return cpu_states[0];
|
||||
LOG_ERROR(Service_Audio, "Invalid voice cpu state index {:04X}", index);
|
||||
}
|
||||
return cpu_states[index];
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <algorithm>
|
||||
#include "audio_core/renderer/memory/pool_mapper.h"
|
||||
#include "audio_core/renderer/voice/voice_context.h"
|
||||
#include "audio_core/renderer/voice/voice_info.h"
|
||||
@@ -390,7 +388,7 @@ bool VoiceInfo::UpdateForCommandGeneration(VoiceContext& voice_context) {
|
||||
is_new = false;
|
||||
}
|
||||
|
||||
for (s8 channel = 0; channel < std::min(channel_count, static_cast<s8>(MaxChannels)); channel++) {
|
||||
for (s8 channel = 0; channel < channel_count; channel++) {
|
||||
voice_states[channel] = &voice_context.GetDspSharedState(channel_resource_ids[channel]);
|
||||
}
|
||||
|
||||
|
||||
@@ -135,14 +135,6 @@ public:
|
||||
static_assert(sizeof(BiquadFilterParameter) == 0xC,
|
||||
"VoiceInfo::BiquadFilterParameter has the wrong size!");
|
||||
|
||||
struct BiquadFilterParameterFloat {
|
||||
/* 0x00 */ bool enabled;
|
||||
/* 0x04 */ std::array<f32, 3> b;
|
||||
/* 0x10 */ std::array<f32, 2> a;
|
||||
};
|
||||
static_assert(sizeof(BiquadFilterParameterFloat) == 0x18,
|
||||
"VoiceInfo::BiquadFilterParameterFloat has the wrong size!");
|
||||
|
||||
struct InParameter {
|
||||
/* 0x000 */ u32 id;
|
||||
/* 0x004 */ u32 node_id;
|
||||
@@ -176,39 +168,6 @@ public:
|
||||
};
|
||||
static_assert(sizeof(InParameter) == 0x170, "VoiceInfo::InParameter has the wrong size!");
|
||||
|
||||
struct InParameterFloat {
|
||||
/* 0x000 */ u32 id;
|
||||
/* 0x004 */ u32 node_id;
|
||||
/* 0x008 */ bool is_new;
|
||||
/* 0x009 */ bool in_use;
|
||||
/* 0x00A */ PlayState play_state;
|
||||
/* 0x00B */ SampleFormat sample_format;
|
||||
/* 0x00C */ u32 sample_rate;
|
||||
/* 0x010 */ s32 priority;
|
||||
/* 0x014 */ s32 sort_order;
|
||||
/* 0x018 */ u32 channel_count;
|
||||
/* 0x01C */ f32 pitch;
|
||||
/* 0x020 */ f32 volume;
|
||||
/* 0x024 */ std::array<BiquadFilterParameterFloat, MaxBiquadFilters> biquads;
|
||||
/* 0x0C4 */ u32 wave_buffer_count;
|
||||
/* 0x0C8 */ u16 wave_buffer_index;
|
||||
/* 0x0CA */ char unk0CA[0x6];
|
||||
/* 0x0D0 */ CpuAddr src_data_address;
|
||||
/* 0x0D8 */ u64 src_data_size;
|
||||
/* 0x0E0 */ u32 mix_id;
|
||||
/* 0x0E4 */ u32 splitter_id;
|
||||
/* 0x0E8 */ std::array<WaveBufferInternal, MaxWaveBuffers> wave_buffer_internal;
|
||||
/* 0x1C8 */ std::array<u32, MaxChannels> channel_resource_ids;
|
||||
/* 0x1E0 */ bool clear_voice_drop;
|
||||
/* 0x1E1 */ u8 flush_buffer_count;
|
||||
/* 0x1E2 */ char unk1E2[0x2];
|
||||
/* 0x1E4 */ Flags flags;
|
||||
/* 0x1E5 */ char unk1E5[0x1];
|
||||
/* 0x1E6 */ SrcQuality src_quality;
|
||||
/* 0x1E7 */ char unk1E7[0x11];
|
||||
};
|
||||
// static_assert(sizeof(InParameterFloat) == 0x1F8, "VoiceInfo::InParameterFloat has the wrong size!");
|
||||
|
||||
struct OutStatus {
|
||||
/* 0x00 */ u64 played_sample_count;
|
||||
/* 0x08 */ u32 wave_buffers_consumed;
|
||||
|
||||
@@ -66,6 +66,5 @@ struct VoiceState {
|
||||
/// Number of times the wavebuffer has looped
|
||||
s32 loop_count;
|
||||
};
|
||||
// static_assert(sizeof(VoiceState) == 0x220, "VoiceState has the wrong size!");
|
||||
|
||||
} // namespace AudioCore::Renderer
|
||||
|
||||
Reference in New Issue
Block a user