From 0f06016cc7081e81d7b226d8f2e49100879494cd Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Sat, 11 Feb 2023 01:50:14 +0100 Subject: [PATCH] early-access version 3381 --- README.md | 2 +- src/audio_core/device/audio_buffers.h | 20 +++++----- src/audio_core/device/device_session.cpp | 16 ++++---- src/audio_core/device/device_session.h | 2 +- src/audio_core/in/audio_in_system.cpp | 14 ++++--- src/audio_core/out/audio_out_system.cpp | 14 ++++--- .../renderer/command/command_generator.cpp | 2 +- .../renderer/command/data_source/decode.cpp | 14 ++++--- .../renderer/command/effect/aux_.cpp | 14 +++++++ .../renderer/command/effect/biquad_filter.cpp | 38 ++++++++----------- .../renderer/command/effect/compressor.cpp | 11 ++++-- .../renderer/command/effect/delay.cpp | 15 +++++--- .../renderer/command/effect/i3dl2_reverb.cpp | 7 +++- .../renderer/command/effect/light_limiter.cpp | 17 ++++++--- .../renderer/command/effect/reverb.cpp | 15 +++++--- .../renderer/command/sink/circular_buffer.cpp | 5 ++- .../renderer/command/sink/device.cpp | 3 +- src/audio_core/renderer/voice/voice_state.h | 8 ++-- src/audio_core/sink/null_sink.h | 3 +- src/audio_core/sink/sink_stream.cpp | 8 ++-- src/audio_core/sink/sink_stream.h | 3 +- src/common/scratch_buffer.h | 18 +++++++++ 22 files changed, 155 insertions(+), 94 deletions(-) diff --git a/README.md b/README.md index 8cc1f3ead..4b8a8295c 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 3380. +This is the source code for early-access 3381. ## Legal Notice diff --git a/src/audio_core/device/audio_buffers.h b/src/audio_core/device/audio_buffers.h index 1e1616f4e..e79abaf5b 100755 --- a/src/audio_core/device/audio_buffers.h +++ b/src/audio_core/device/audio_buffers.h @@ -48,7 +48,7 @@ public: * * @param out_buffers - The buffers which were registered. */ - void RegisterBuffers(std::vector& out_buffers) { + void RegisterBuffers(std::span out_buffers, u32& out_size) { std::scoped_lock l{lock}; const s32 to_register{std::min(std::min(appended_count, BufferAppendLimit), BufferAppendLimit - registered_count)}; @@ -59,7 +59,7 @@ public: index += N; } - out_buffers.push_back(buffers[index]); + out_buffers[out_size++] = buffers[index]; registered_count++; registered_index = (registered_index + 1) % append_limit; @@ -162,7 +162,7 @@ public: * @param max_buffers - Maximum number of buffers to released. * @return The number of buffers released. */ - u32 GetRegisteredAppendedBuffers(std::vector& buffers_flushed, u32 max_buffers) { + u32 GetRegisteredAppendedBuffers(std::span out_buffers, u32 max_buffers) { std::scoped_lock l{lock}; if (registered_count + appended_count == 0) { return 0; @@ -174,19 +174,20 @@ public: return 0; } + u32 buffers_flushed{0}; while (registered_count > 0) { auto index{registered_index - registered_count}; if (index < 0) { index += N; } - buffers_flushed.push_back(buffers[index]); + out_buffers[buffers_flushed++] = buffers[index]; registered_count--; released_count++; released_index = (released_index + 1) % append_limit; - if (buffers_flushed.size() >= buffers_to_flush) { + if (buffers_flushed >= buffers_to_flush) { break; } } @@ -197,18 +198,18 @@ public: index += N; } - buffers_flushed.push_back(buffers[index]); + out_buffers[buffers_flushed++] = buffers[index]; appended_count--; released_count++; released_index = (released_index + 1) % append_limit; - if (buffers_flushed.size() >= buffers_to_flush) { + if (buffers_flushed >= buffers_to_flush) { break; } } - return static_cast(buffers_flushed.size()); + return buffers_flushed; } /** @@ -270,8 +271,9 @@ public: */ bool FlushBuffers(u32& buffers_released) { std::scoped_lock l{lock}; - std::vector buffers_flushed{}; + static Common::ScratchBuffer buffers_flushed{}; + buffers_flushed.resize_destructive(append_limit); buffers_released = GetRegisteredAppendedBuffers(buffers_flushed, append_limit); if (registered_count > 0) { diff --git a/src/audio_core/device/device_session.cpp b/src/audio_core/device/device_session.cpp index f60bd14e9..fcf3d2b79 100755 --- a/src/audio_core/device/device_session.cpp +++ b/src/audio_core/device/device_session.cpp @@ -6,6 +6,7 @@ #include "audio_core/device/audio_buffer.h" #include "audio_core/device/device_session.h" #include "audio_core/sink/sink_stream.h" +#include "common/scratch_buffer.h" #include "core/core.h" #include "core/core_timing.h" #include "core/memory.h" @@ -79,21 +80,22 @@ void DeviceSession::ClearBuffers() { } } -void DeviceSession::AppendBuffers(std::span buffers) const { - for (const auto& buffer : buffers) { +void DeviceSession::AppendBuffers(std::span buffers, u32 out_size) const { + static Common::ScratchBuffer samples{}; + + for (u32 i = 0; i < out_size; i++) { Sink::SinkBuffer new_buffer{ - .frames = buffer.size / (channel_count * sizeof(s16)), + .frames = buffers[i].size / (channel_count * sizeof(s16)), .frames_played = 0, - .tag = buffer.tag, + .tag = buffers[i].tag, .consumed = false, }; if (type == Sink::StreamType::In) { - std::vector samples{}; stream->AppendBuffer(new_buffer, samples); } else { - std::vector samples(buffer.size / sizeof(s16)); - system.Memory().ReadBlockUnsafe(buffer.samples, samples.data(), buffer.size); + samples.resize_destructive(buffers[i].size / sizeof(s16)); + system.Memory().ReadBlockUnsafe(buffers[i].samples, samples.data(), buffers[i].size); stream->AppendBuffer(new_buffer, samples); } } diff --git a/src/audio_core/device/device_session.h b/src/audio_core/device/device_session.h index f65c850bd..e79e1b1d0 100755 --- a/src/audio_core/device/device_session.h +++ b/src/audio_core/device/device_session.h @@ -62,7 +62,7 @@ public: * * @param buffers - The buffers to play. */ - void AppendBuffers(std::span buffers) const; + void AppendBuffers(std::span buffers, u32 out_size) const; /** * (Audio In only) Pop samples from the backend, and write them back to this buffer's address. diff --git a/src/audio_core/in/audio_in_system.cpp b/src/audio_core/in/audio_in_system.cpp index 45aade449..90c561291 100755 --- a/src/audio_core/in/audio_in_system.cpp +++ b/src/audio_core/in/audio_in_system.cpp @@ -89,9 +89,10 @@ Result System::Start() { session->Start(); state = State::Started; - std::vector buffers_to_flush{}; - buffers.RegisterBuffers(buffers_to_flush); - session->AppendBuffers(buffers_to_flush); + std::array buffers_to_flush{}; + u32 out_size{0}; + buffers.RegisterBuffers(buffers_to_flush, out_size); + session->AppendBuffers(buffers_to_flush, out_size); session->SetRingSize(static_cast(buffers_to_flush.size())); return ResultSuccess; @@ -134,9 +135,10 @@ bool System::AppendBuffer(const AudioInBuffer& buffer, const u64 tag) { void System::RegisterBuffers() { if (state == State::Started) { - std::vector registered_buffers{}; - buffers.RegisterBuffers(registered_buffers); - session->AppendBuffers(registered_buffers); + std::array registered_buffers{}; + u32 out_size{0}; + buffers.RegisterBuffers(registered_buffers, out_size); + session->AppendBuffers(registered_buffers, out_size); } } diff --git a/src/audio_core/out/audio_out_system.cpp b/src/audio_core/out/audio_out_system.cpp index 9f75cd1a8..83cbf8543 100755 --- a/src/audio_core/out/audio_out_system.cpp +++ b/src/audio_core/out/audio_out_system.cpp @@ -89,9 +89,10 @@ Result System::Start() { session->Start(); state = State::Started; - std::vector buffers_to_flush{}; - buffers.RegisterBuffers(buffers_to_flush); - session->AppendBuffers(buffers_to_flush); + std::array buffers_to_flush{}; + u32 out_size{0}; + buffers.RegisterBuffers(buffers_to_flush, out_size); + session->AppendBuffers(buffers_to_flush, out_size); session->SetRingSize(static_cast(buffers_to_flush.size())); return ResultSuccess; @@ -134,9 +135,10 @@ bool System::AppendBuffer(const AudioOutBuffer& buffer, u64 tag) { void System::RegisterBuffers() { if (state == State::Started) { - std::vector registered_buffers{}; - buffers.RegisterBuffers(registered_buffers); - session->AppendBuffers(registered_buffers); + std::array registered_buffers{}; + u32 out_size{0}; + buffers.RegisterBuffers(registered_buffers, out_size); + session->AppendBuffers(registered_buffers, out_size); } } diff --git a/src/audio_core/renderer/command/command_generator.cpp b/src/audio_core/renderer/command/command_generator.cpp index cf90e9140..d8ae99461 100755 --- a/src/audio_core/renderer/command/command_generator.cpp +++ b/src/audio_core/renderer/command/command_generator.cpp @@ -46,7 +46,7 @@ void CommandGenerator::GenerateDataSourceCommand(VoiceInfo& voice_info, while (destination != nullptr) { if (destination->IsConfigured()) { auto mix_id{destination->GetMixId()}; - if (mix_id < mix_context.GetCount()) { + if (mix_id < mix_context.GetCount() && mix_id != -1) { auto mix_info{mix_context.GetInfo(mix_id)}; command_buffer.GenerateDepopPrepareCommand( voice_info.node_id, voice_state, render_context.depop_buffer, diff --git a/src/audio_core/renderer/command/data_source/decode.cpp b/src/audio_core/renderer/command/data_source/decode.cpp index d391be35d..1e85490dc 100755 --- a/src/audio_core/renderer/command/data_source/decode.cpp +++ b/src/audio_core/renderer/command/data_source/decode.cpp @@ -8,6 +8,7 @@ #include "audio_core/renderer/command/resample/resample.h" #include "common/fixed_point.h" #include "common/logging/log.h" +#include "common/scratch_buffer.h" #include "core/memory.h" namespace AudioCore::AudioRenderer { @@ -29,6 +30,7 @@ static u32 DecodePcm(Core::Memory::Memory& memory, std::span out_buffer, const DecodeArg& req) { constexpr s32 min{std::numeric_limits::min()}; constexpr s32 max{std::numeric_limits::max()}; + static Common::ScratchBuffer samples; if (req.buffer == 0 || req.buffer_size == 0) { return 0; @@ -49,7 +51,7 @@ static u32 DecodePcm(Core::Memory::Memory& memory, std::span out_buffer, const u64 size{channel_count * samples_to_decode}; const u64 size_bytes{size * sizeof(T)}; - std::vector samples(size); + samples.resize_destructive(size); memory.ReadBlockUnsafe(source, samples.data(), size_bytes); if constexpr (std::is_floating_point_v) { @@ -73,7 +75,7 @@ static u32 DecodePcm(Core::Memory::Memory& memory, std::span out_buffer, } const VAddr source{req.buffer + ((req.start_offset + req.offset) * sizeof(T))}; - std::vector samples(samples_to_decode); + samples.resize_destructive(samples_to_decode); memory.ReadBlockUnsafe(source, samples.data(), samples_to_decode * sizeof(T)); if constexpr (std::is_floating_point_v) { @@ -103,6 +105,7 @@ static u32 DecodeAdpcm(Core::Memory::Memory& memory, std::span out_buffer, const DecodeArg& req) { constexpr u32 SamplesPerFrame{14}; constexpr u32 NibblesPerFrame{16}; + static Common::ScratchBuffer wavebuffer; if (req.buffer == 0 || req.buffer_size == 0) { return 0; @@ -138,7 +141,7 @@ static u32 DecodeAdpcm(Core::Memory::Memory& memory, std::span out_buffer, } const auto size{std::max((samples_to_process / 8U) * SamplesPerFrame, 8U)}; - std::vector wavebuffer(size); + wavebuffer.resize_destructive(size); memory.ReadBlockUnsafe(req.buffer + position_in_frame / 2, wavebuffer.data(), wavebuffer.size()); @@ -227,6 +230,8 @@ static u32 DecodeAdpcm(Core::Memory::Memory& memory, std::span out_buffer, * @param args - The wavebuffer data, and information for how to decode it. */ void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuffersArgs& args) { + Common::ScratchBuffer temp_buffer(TempBufferSize); + auto& voice_state{*args.voice_state}; auto remaining_sample_count{args.sample_count}; auto fraction{voice_state.fraction}; @@ -256,9 +261,8 @@ void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuf bool is_buffer_starved{false}; u32 offset{voice_state.offset}; - + std::memset(temp_buffer.data(), 0, temp_buffer.size() * sizeof(s16)); auto output_buffer{args.output}; - std::vector temp_buffer(TempBufferSize, 0); while (remaining_sample_count > 0) { const auto samples_to_write{std::min(remaining_sample_count, max_remaining_sample_count)}; diff --git a/src/audio_core/renderer/command/effect/aux_.cpp b/src/audio_core/renderer/command/effect/aux_.cpp index e3e3e4d5f..eb4624fd7 100755 --- a/src/audio_core/renderer/command/effect/aux_.cpp +++ b/src/audio_core/renderer/command/effect/aux_.cpp @@ -4,6 +4,7 @@ #include "audio_core/renderer/adsp/command_list_processor.h" #include "audio_core/renderer/command/effect/aux_.h" #include "audio_core/renderer/effect/aux_.h" +#include "core/core.h" #include "core/memory.h" namespace AudioCore::AudioRenderer { @@ -174,6 +175,19 @@ void AuxCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& process } void AuxCommand::Process(const ADSP::CommandListProcessor& processor) { + // HACK! + // Ignore aux for Super Mario Odyssey and Metroid Prime Remastered. + // For some reason these games receive output samples, and then send them back in as input + // again. Problem is the data being sent back in is slightly offset from the current output by + // 240 or 480 samples, leading to a very fast echoing effect, which should not be there. + // Timing issue or some bug in the code? + // We can't disable this unconditionally as some games rely on it for synchronisation and will + // softlock without it (Age of Calamity). + const auto program_id = processor.system->GetCurrentProcessProgramID(); + if (program_id == 0x0100000000010000ull || program_id == 0x010012101468C000ull) { + return; + } + auto input_buffer{ processor.mix_buffers.subspan(input * processor.sample_count, processor.sample_count)}; auto output_buffer{ diff --git a/src/audio_core/renderer/command/effect/biquad_filter.cpp b/src/audio_core/renderer/command/effect/biquad_filter.cpp index 277100b33..7c32fc390 100755 --- a/src/audio_core/renderer/command/effect/biquad_filter.cpp +++ b/src/audio_core/renderer/command/effect/biquad_filter.cpp @@ -4,6 +4,7 @@ #include "audio_core/renderer/adsp/command_list_processor.h" #include "audio_core/renderer/command/effect/biquad_filter.h" #include "audio_core/renderer/voice/voice_state.h" +#include "common/bit_cast.h" namespace AudioCore::AudioRenderer { /** @@ -19,21 +20,21 @@ namespace AudioCore::AudioRenderer { void ApplyBiquadFilterFloat(std::span output, std::span input, std::array& b_, std::array& a_, VoiceState::BiquadFilterState& state, const u32 sample_count) { - constexpr s64 min{std::numeric_limits::min()}; - constexpr s64 max{std::numeric_limits::max()}; + constexpr f64 min{std::numeric_limits::min()}; + constexpr f64 max{std::numeric_limits::max()}; std::array b{Common::FixedPoint<50, 14>::from_base(b_[0]).to_double(), Common::FixedPoint<50, 14>::from_base(b_[1]).to_double(), Common::FixedPoint<50, 14>::from_base(b_[2]).to_double()}; std::array a{Common::FixedPoint<50, 14>::from_base(a_[0]).to_double(), Common::FixedPoint<50, 14>::from_base(a_[1]).to_double()}; - std::array s{state.s0.to_double(), state.s1.to_double(), state.s2.to_double(), - state.s3.to_double()}; + std::array s{Common::BitCast(state.s0), Common::BitCast(state.s1), + Common::BitCast(state.s2), Common::BitCast(state.s3)}; for (u32 i = 0; i < sample_count; i++) { f64 in_sample{static_cast(input[i])}; auto sample{in_sample * b[0] + s[0] * b[1] + s[1] * b[2] + s[2] * a[0] + s[3] * a[1]}; - output[i] = static_cast(std::clamp(static_cast(sample), min, max)); + output[i] = static_cast(std::clamp(sample, min, max)); s[1] = s[0]; s[0] = in_sample; @@ -41,10 +42,10 @@ void ApplyBiquadFilterFloat(std::span output, std::span input, s[2] = sample; } - state.s0 = s[0]; - state.s1 = s[1]; - state.s2 = s[2]; - state.s3 = s[3]; + state.s0 = Common::BitCast(s[0]); + state.s1 = Common::BitCast(s[1]); + state.s2 = Common::BitCast(s[2]); + state.s3 = Common::BitCast(s[3]); } /** @@ -58,29 +59,20 @@ void ApplyBiquadFilterFloat(std::span output, std::span input, * @param sample_count - Number of samples to process. */ static void ApplyBiquadFilterInt(std::span output, std::span input, - std::array& b_, std::array& a_, + std::array& b, std::array& a, VoiceState::BiquadFilterState& state, const u32 sample_count) { constexpr s64 min{std::numeric_limits::min()}; constexpr s64 max{std::numeric_limits::max()}; - std::array, 3> b{ - Common::FixedPoint<50, 14>::from_base(b_[0]), - Common::FixedPoint<50, 14>::from_base(b_[1]), - Common::FixedPoint<50, 14>::from_base(b_[2]), - }; - std::array, 3> a{ - Common::FixedPoint<50, 14>::from_base(a_[0]), - Common::FixedPoint<50, 14>::from_base(a_[1]), - }; for (u32 i = 0; i < sample_count; i++) { - s64 in_sample{input[i]}; - auto sample{in_sample * b[0] + state.s0}; - const auto out_sample{std::clamp(sample.to_long(), min, max)}; + const s64 in_sample{input[i]}; + const s64 sample{in_sample * b[0] + state.s0}; + const s64 out_sample{std::clamp((sample + (1 << 13)) >> 14, min, max)}; output[i] = static_cast(out_sample); state.s0 = state.s1 + b[1] * in_sample + a[0] * out_sample; - state.s1 = 0 + b[2] * in_sample + a[1] * out_sample; + state.s1 = b[2] * in_sample + a[1] * out_sample; } } diff --git a/src/audio_core/renderer/command/effect/compressor.cpp b/src/audio_core/renderer/command/effect/compressor.cpp index 6f4032615..0b183c334 100755 --- a/src/audio_core/renderer/command/effect/compressor.cpp +++ b/src/audio_core/renderer/command/effect/compressor.cpp @@ -8,6 +8,7 @@ #include "audio_core/renderer/adsp/command_list_processor.h" #include "audio_core/renderer/command/effect/compressor.h" #include "audio_core/renderer/effect/compressor.h" +#include "common/scratch_buffer.h" namespace AudioCore::AudioRenderer { @@ -44,8 +45,8 @@ static void InitializeCompressorEffect(const CompressorInfo::ParameterVersion2& static void ApplyCompressorEffect(const CompressorInfo::ParameterVersion2& params, CompressorInfo::State& state, bool enabled, - std::vector> input_buffers, - std::vector> output_buffers, u32 sample_count) { + std::span> input_buffers, + std::span> output_buffers, u32 sample_count) { if (enabled) { auto state_00{state.unk_00}; auto state_04{state.unk_04}; @@ -124,8 +125,10 @@ void CompressorCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& } void CompressorCommand::Process(const ADSP::CommandListProcessor& processor) { - std::vector> input_buffers(parameter.channel_count); - std::vector> output_buffers(parameter.channel_count); + static Common::ScratchBuffer> input_buffers{}; + static Common::ScratchBuffer> output_buffers{}; + input_buffers.resize_destructive(parameter.channel_count); + output_buffers.resize_destructive(parameter.channel_count); for (s16 i = 0; i < parameter.channel_count; i++) { input_buffers[i] = processor.mix_buffers.subspan(inputs[i] * processor.sample_count, diff --git a/src/audio_core/renderer/command/effect/delay.cpp b/src/audio_core/renderer/command/effect/delay.cpp index 595667446..7ac6d4bfa 100755 --- a/src/audio_core/renderer/command/effect/delay.cpp +++ b/src/audio_core/renderer/command/effect/delay.cpp @@ -3,6 +3,7 @@ #include "audio_core/renderer/adsp/command_list_processor.h" #include "audio_core/renderer/command/effect/delay.h" +#include "common/scratch_buffer.h" namespace AudioCore::AudioRenderer { /** @@ -74,8 +75,8 @@ static void InitializeDelayEffect(const DelayInfo::ParameterVersion1& params, */ template static void ApplyDelay(const DelayInfo::ParameterVersion1& params, DelayInfo::State& state, - std::vector>& inputs, - std::vector>& outputs, const u32 sample_count) { + std::span> inputs, std::span> outputs, + const u32 sample_count) { for (u32 sample_index = 0; sample_index < sample_count; sample_index++) { std::array, NumChannels> input_samples{}; for (u32 channel = 0; channel < NumChannels; channel++) { @@ -153,8 +154,8 @@ static void ApplyDelay(const DelayInfo::ParameterVersion1& params, DelayInfo::St * @param sample_count - Number of samples to process. */ static void ApplyDelayEffect(const DelayInfo::ParameterVersion1& params, DelayInfo::State& state, - const bool enabled, std::vector>& inputs, - std::vector>& outputs, const u32 sample_count) { + const bool enabled, std::span> inputs, + std::span> outputs, const u32 sample_count) { if (!IsChannelCountValid(params.channel_count)) { LOG_ERROR(Service_Audio, "Invalid delay channels {}", params.channel_count); @@ -208,8 +209,10 @@ void DelayCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& proce } void DelayCommand::Process(const ADSP::CommandListProcessor& processor) { - std::vector> input_buffers(parameter.channel_count); - std::vector> output_buffers(parameter.channel_count); + static Common::ScratchBuffer> input_buffers{}; + static Common::ScratchBuffer> output_buffers{}; + input_buffers.resize_destructive(parameter.channel_count); + output_buffers.resize_destructive(parameter.channel_count); for (s16 i = 0; i < parameter.channel_count; i++) { input_buffers[i] = processor.mix_buffers.subspan(inputs[i] * processor.sample_count, diff --git a/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp b/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp index 5003b916b..d6651a7f7 100755 --- a/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp +++ b/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp @@ -6,6 +6,7 @@ #include "audio_core/renderer/adsp/command_list_processor.h" #include "audio_core/renderer/command/effect/i3dl2_reverb.h" #include "common/polyfill_ranges.h" +#include "common/scratch_buffer.h" namespace AudioCore::AudioRenderer { @@ -408,8 +409,10 @@ void I3dl2ReverbCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& } void I3dl2ReverbCommand::Process(const ADSP::CommandListProcessor& processor) { - std::vector> input_buffers(parameter.channel_count); - std::vector> output_buffers(parameter.channel_count); + static Common::ScratchBuffer> input_buffers{}; + static Common::ScratchBuffer> output_buffers{}; + input_buffers.resize_destructive(parameter.channel_count); + output_buffers.resize_destructive(parameter.channel_count); for (u32 i = 0; i < parameter.channel_count; i++) { input_buffers[i] = processor.mix_buffers.subspan(inputs[i] * processor.sample_count, diff --git a/src/audio_core/renderer/command/effect/light_limiter.cpp b/src/audio_core/renderer/command/effect/light_limiter.cpp index 4c57350a9..d1a72f5cd 100755 --- a/src/audio_core/renderer/command/effect/light_limiter.cpp +++ b/src/audio_core/renderer/command/effect/light_limiter.cpp @@ -3,6 +3,7 @@ #include "audio_core/renderer/adsp/command_list_processor.h" #include "audio_core/renderer/command/effect/light_limiter.h" +#include "common/scratch_buffer.h" namespace AudioCore::AudioRenderer { /** @@ -47,8 +48,8 @@ static void InitializeLightLimiterEffect(const LightLimiterInfo::ParameterVersio */ static void ApplyLightLimiterEffect(const LightLimiterInfo::ParameterVersion2& params, LightLimiterInfo::State& state, const bool enabled, - std::vector>& inputs, - std::vector>& outputs, const u32 sample_count, + std::span> inputs, + std::span> outputs, const u32 sample_count, LightLimiterInfo::StatisticsInternal* statistics) { constexpr s64 min{std::numeric_limits::min()}; constexpr s64 max{std::numeric_limits::max()}; @@ -147,8 +148,10 @@ void LightLimiterVersion1Command::Dump([[maybe_unused]] const ADSP::CommandListP } void LightLimiterVersion1Command::Process(const ADSP::CommandListProcessor& processor) { - std::vector> input_buffers(parameter.channel_count); - std::vector> output_buffers(parameter.channel_count); + static Common::ScratchBuffer> input_buffers{}; + static Common::ScratchBuffer> output_buffers{}; + input_buffers.resize_destructive(parameter.channel_count); + output_buffers.resize_destructive(parameter.channel_count); for (u32 i = 0; i < parameter.channel_count; i++) { input_buffers[i] = processor.mix_buffers.subspan(inputs[i] * processor.sample_count, @@ -190,8 +193,10 @@ void LightLimiterVersion2Command::Dump([[maybe_unused]] const ADSP::CommandListP } void LightLimiterVersion2Command::Process(const ADSP::CommandListProcessor& processor) { - std::vector> input_buffers(parameter.channel_count); - std::vector> output_buffers(parameter.channel_count); + static Common::ScratchBuffer> input_buffers{}; + static Common::ScratchBuffer> output_buffers{}; + input_buffers.resize_destructive(parameter.channel_count); + output_buffers.resize_destructive(parameter.channel_count); for (u32 i = 0; i < parameter.channel_count; i++) { input_buffers[i] = processor.mix_buffers.subspan(inputs[i] * processor.sample_count, diff --git a/src/audio_core/renderer/command/effect/reverb.cpp b/src/audio_core/renderer/command/effect/reverb.cpp index 25c2910aa..d9403f9dd 100755 --- a/src/audio_core/renderer/command/effect/reverb.cpp +++ b/src/audio_core/renderer/command/effect/reverb.cpp @@ -7,6 +7,7 @@ #include "audio_core/renderer/adsp/command_list_processor.h" #include "audio_core/renderer/command/effect/reverb.h" #include "common/polyfill_ranges.h" +#include "common/scratch_buffer.h" namespace AudioCore::AudioRenderer { @@ -250,8 +251,8 @@ static Common::FixedPoint<50, 14> Axfx2AllPassTick(ReverbInfo::ReverbDelayLine& */ template static void ApplyReverbEffect(const ReverbInfo::ParameterVersion2& params, ReverbInfo::State& state, - std::vector>& inputs, - std::vector>& outputs, const u32 sample_count) { + std::span> inputs, + std::span> outputs, const u32 sample_count) { constexpr std::array OutTapIndexes1Ch{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; @@ -368,8 +369,8 @@ static void ApplyReverbEffect(const ReverbInfo::ParameterVersion2& params, Rever * @param sample_count - Number of samples to process. */ static void ApplyReverbEffect(const ReverbInfo::ParameterVersion2& params, ReverbInfo::State& state, - const bool enabled, std::vector>& inputs, - std::vector>& outputs, const u32 sample_count) { + const bool enabled, std::span> inputs, + std::span> outputs, const u32 sample_count) { if (enabled) { switch (params.channel_count) { case 0: @@ -411,8 +412,10 @@ void ReverbCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& proc } void ReverbCommand::Process(const ADSP::CommandListProcessor& processor) { - std::vector> input_buffers(parameter.channel_count); - std::vector> output_buffers(parameter.channel_count); + static Common::ScratchBuffer> input_buffers{}; + static Common::ScratchBuffer> output_buffers{}; + input_buffers.resize_destructive(parameter.channel_count); + output_buffers.resize_destructive(parameter.channel_count); for (u32 i = 0; i < parameter.channel_count; i++) { input_buffers[i] = processor.mix_buffers.subspan(inputs[i] * processor.sample_count, diff --git a/src/audio_core/renderer/command/sink/circular_buffer.cpp b/src/audio_core/renderer/command/sink/circular_buffer.cpp index 64cd1b0cb..dacb8c66a 100755 --- a/src/audio_core/renderer/command/sink/circular_buffer.cpp +++ b/src/audio_core/renderer/command/sink/circular_buffer.cpp @@ -5,6 +5,7 @@ #include "audio_core/renderer/adsp/command_list_processor.h" #include "audio_core/renderer/command/sink/circular_buffer.h" +#include "common/scratch_buffer.h" #include "core/memory.h" namespace AudioCore::AudioRenderer { @@ -24,7 +25,9 @@ void CircularBufferSinkCommand::Process(const ADSP::CommandListProcessor& proces constexpr s32 min{std::numeric_limits::min()}; constexpr s32 max{std::numeric_limits::max()}; - std::vector output(processor.sample_count); + static Common::ScratchBuffer output{}; + output.resize_destructive(processor.sample_count); + for (u32 channel = 0; channel < input_count; channel++) { auto input{processor.mix_buffers.subspan(inputs[channel] * processor.sample_count, processor.sample_count)}; diff --git a/src/audio_core/renderer/command/sink/device.cpp b/src/audio_core/renderer/command/sink/device.cpp index 22e2a8464..846d0a0c0 100755 --- a/src/audio_core/renderer/command/sink/device.cpp +++ b/src/audio_core/renderer/command/sink/device.cpp @@ -33,7 +33,8 @@ void DeviceSinkCommand::Process(const ADSP::CommandListProcessor& processor) { .consumed{false}, }; - std::vector samples(out_buffer.frames * input_count); + static Common::ScratchBuffer samples{}; + samples.resize_destructive(out_buffer.frames * input_count); for (u32 channel = 0; channel < input_count; channel++) { const auto offset{inputs[channel] * out_buffer.frames}; diff --git a/src/audio_core/renderer/voice/voice_state.h b/src/audio_core/renderer/voice/voice_state.h index 82dc76f44..b6552c381 100755 --- a/src/audio_core/renderer/voice/voice_state.h +++ b/src/audio_core/renderer/voice/voice_state.h @@ -19,10 +19,10 @@ struct VoiceState { * State of the voice's biquad filter. */ struct BiquadFilterState { - Common::FixedPoint<50, 14> s0; - Common::FixedPoint<50, 14> s1; - Common::FixedPoint<50, 14> s2; - Common::FixedPoint<50, 14> s3; + s64 s0; + s64 s1; + s64 s2; + s64 s3; }; /** diff --git a/src/audio_core/sink/null_sink.h b/src/audio_core/sink/null_sink.h index 319271c2b..2ed81c4f6 100755 --- a/src/audio_core/sink/null_sink.h +++ b/src/audio_core/sink/null_sink.h @@ -9,6 +9,7 @@ #include "audio_core/sink/sink.h" #include "audio_core/sink/sink_stream.h" +#include "common/scratch_buffer.h" namespace Core { class System; @@ -20,7 +21,7 @@ public: explicit NullSinkStreamImpl(Core::System& system_, StreamType type_) : SinkStream{system_, type_} {} ~NullSinkStreamImpl() override {} - void AppendBuffer(SinkBuffer&, std::vector&) override {} + void AppendBuffer(SinkBuffer&, Common::ScratchBuffer&) override {} std::vector ReleaseBuffer(u64) override { return {}; } diff --git a/src/audio_core/sink/sink_stream.cpp b/src/audio_core/sink/sink_stream.cpp index 8412983cc..9d2bae2b0 100755 --- a/src/audio_core/sink/sink_stream.cpp +++ b/src/audio_core/sink/sink_stream.cpp @@ -17,7 +17,7 @@ namespace AudioCore::Sink { -void SinkStream::AppendBuffer(SinkBuffer& buffer, std::vector& samples) { +void SinkStream::AppendBuffer(SinkBuffer& buffer, Common::ScratchBuffer& samples) { if (type == StreamType::In) { queue.enqueue(buffer); queued_buffers++; @@ -71,7 +71,9 @@ void SinkStream::AppendBuffer(SinkBuffer& buffer, std::vector& samples) { // We need moar samples! Not all games will provide 6 channel audio. // TODO: Implement some upmixing here. Currently just passthrough, with other // channels left as silence. - std::vector new_samples(samples.size() / system_channels * device_channels, 0); + static Common::ScratchBuffer new_samples{}; + new_samples.resize_destructive(samples.size() / system_channels * device_channels); + std::memset(new_samples.data(), 0, new_samples.size() * sizeof(s16)); for (u32 read_index = 0, write_index = 0; read_index < samples.size(); read_index += system_channels, write_index += device_channels) { @@ -100,7 +102,7 @@ void SinkStream::AppendBuffer(SinkBuffer& buffer, std::vector& samples) { } } - samples_buffer.Push(samples); + samples_buffer.Push(samples.data(), samples.size()); queue.enqueue(buffer); queued_buffers++; } diff --git a/src/audio_core/sink/sink_stream.h b/src/audio_core/sink/sink_stream.h index 39b1bc3ca..ae867a5ef 100755 --- a/src/audio_core/sink/sink_stream.h +++ b/src/audio_core/sink/sink_stream.h @@ -14,6 +14,7 @@ #include "common/common_types.h" #include "common/reader_writer_queue.h" #include "common/ring_buffer.h" +#include "common/scratch_buffer.h" namespace Core { class System; @@ -169,7 +170,7 @@ public: * @param buffer - Audio buffer information to be queued. * @param samples - The s16 samples to be queue for playback. */ - virtual void AppendBuffer(SinkBuffer& buffer, std::vector& samples); + virtual void AppendBuffer(SinkBuffer& buffer, Common::ScratchBuffer& samples); /** * Release a buffer. Audio In only, will fill a buffer with recorded samples. diff --git a/src/common/scratch_buffer.h b/src/common/scratch_buffer.h index 1245a5086..62fa9f609 100755 --- a/src/common/scratch_buffer.h +++ b/src/common/scratch_buffer.h @@ -24,6 +24,24 @@ public: ~ScratchBuffer() = default; + ScratchBuffer(ScratchBuffer&& rhs) { + last_requested_size = rhs.last_requested_size; + buffer_capacity = rhs.buffer_capacity; + buffer = std::move(rhs.buffer); + + rhs.last_requested_size = 0; + rhs.buffer_capacity = 0; + } + + void operator=(ScratchBuffer&& rhs) { + last_requested_size = rhs.last_requested_size; + buffer_capacity = rhs.buffer_capacity; + buffer = std::move(rhs.buffer); + + rhs.last_requested_size = 0; + rhs.buffer_capacity = 0; + } + /// This will only grow the buffer's capacity if size is greater than the current capacity. /// The previously held data will remain intact. void resize(size_t size) {