audio_core: Only perform audio stretching if below full speed. (#7201)

This commit is contained in:
Steveice10 2023-11-26 12:06:59 -08:00 committed by GitHub
parent c0ecdb689d
commit 670e9936a4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 83 additions and 52 deletions

View file

@ -13,7 +13,8 @@
namespace AudioCore {
DspInterface::DspInterface() = default;
DspInterface::DspInterface(Core::System& system_) : system(system_) {}
DspInterface::~DspInterface() = default;
void DspInterface::SetSink(AudioCore::SinkType sink_type, std::string_view audio_device) {
@ -32,13 +33,7 @@ Sink& DspInterface::GetSink() {
}
void DspInterface::EnableStretching(bool enable) {
if (perform_time_stretching == enable)
return;
if (!enable) {
flushing_time_stretcher = true;
}
perform_time_stretching = enable;
enable_time_stretching = enable;
}
void DspInterface::OutputFrame(StereoFrame16 frame) {
@ -47,7 +42,7 @@ void DspInterface::OutputFrame(StereoFrame16 frame) {
fifo.Push(frame.data(), frame.size());
auto video_dumper = Core::System::GetInstance().GetVideoDumper();
auto video_dumper = system.GetVideoDumper();
if (video_dumper && video_dumper->IsDumping()) {
video_dumper->AddAudioFrame(std::move(frame));
}
@ -59,15 +54,24 @@ void DspInterface::OutputSample(std::array<s16, 2> sample) {
fifo.Push(&sample, 1);
auto video_dumper = Core::System::GetInstance().GetVideoDumper();
auto video_dumper = system.GetVideoDumper();
if (video_dumper && video_dumper->IsDumping()) {
video_dumper->AddAudioSample(std::move(sample));
}
}
void DspInterface::OutputCallback(s16* buffer, std::size_t num_frames) {
// Determine if we should stretch based on the current emulation speed.
const auto perf_stats = system.GetLastPerfStats();
const auto should_stretch = enable_time_stretching && perf_stats.emulation_speed <= 95;
if (performing_time_stretching && !should_stretch) {
// If we just stopped stretching, flush the stretcher before returning to normal output.
flushing_time_stretcher = true;
}
performing_time_stretching = should_stretch;
std::size_t frames_written = 0;
if (perform_time_stretching) {
if (performing_time_stretching) {
const std::vector<s16> in{fifo.Pop()};
const std::size_t num_in{in.size() / 2};
frames_written = time_stretcher.Process(in.data(), num_in, buffer, num_frames);

View file

@ -13,6 +13,10 @@
#include "common/ring_buffer.h"
#include "core/memory.h"
namespace Core {
class System;
} // namespace Core
namespace Service::DSP {
enum class InterruptType : u32;
} // namespace Service::DSP
@ -24,7 +28,7 @@ enum class SinkType : u32;
class DspInterface {
public:
DspInterface();
DspInterface(Core::System& system_);
virtual ~DspInterface();
DspInterface(const DspInterface&) = delete;
@ -110,7 +114,10 @@ private:
void FlushResidualStretcherAudio();
void OutputCallback(s16* buffer, std::size_t num_frames);
std::atomic<bool> perform_time_stretching = false;
Core::System& system;
std::atomic<bool> enable_time_stretching = false;
std::atomic<bool> performing_time_stretching = false;
std::atomic<bool> flushing_time_stretcher = false;
Common::RingBuffer<s16, 0x2000, 2> fifo;
std::array<s16, 2> last_frame{};

View file

@ -31,7 +31,10 @@ using InterruptType = Service::DSP::InterruptType;
namespace AudioCore {
DspHle::DspHle()
: DspHle(Core::System::GetInstance().Memory(), Core::System::GetInstance().CoreTiming()) {}
: DspHle(Core::System::GetInstance(), Core::System::GetInstance().Memory(),
Core::System::GetInstance().CoreTiming()) {}
DspHle::DspHle(Core::System& system) : DspHle(system, system.Memory(), system.CoreTiming()) {}
template <class Archive>
void DspHle::serialize(Archive& ar, const unsigned int) {
@ -442,8 +445,8 @@ void DspHle::Impl::AudioTickCallback(s64 cycles_late) {
core_timing.ScheduleEvent(audio_frame_ticks - cycles_late, tick_event);
}
DspHle::DspHle(Memory::MemorySystem& memory, Core::Timing& timing)
: impl(std::make_unique<Impl>(*this, memory, timing)) {}
DspHle::DspHle(Core::System& system, Memory::MemorySystem& memory, Core::Timing& timing)
: DspInterface(system), impl(std::make_unique<Impl>(*this, memory, timing)) {}
DspHle::~DspHle() = default;
u16 DspHle::RecvData(u32 register_number) {

View file

@ -14,6 +14,10 @@
#include "core/hle/service/dsp/dsp_dsp.h"
#include "core/memory.h"
namespace Core {
class Timing;
}
namespace Memory {
class MemorySystem;
}
@ -22,7 +26,8 @@ namespace AudioCore {
class DspHle final : public DspInterface {
public:
explicit DspHle(Memory::MemorySystem& memory, Core::Timing& timing);
explicit DspHle(Core::System& system);
explicit DspHle(Core::System& system, Memory::MemorySystem& memory, Core::Timing& timing);
~DspHle();
u16 RecvData(u32 register_number) override;

View file

@ -468,8 +468,12 @@ void DspLle::UnloadComponent() {
impl->UnloadComponent();
}
DspLle::DspLle(Memory::MemorySystem& memory, Core::Timing& timing, bool multithread)
: impl(std::make_unique<Impl>(timing, multithread)) {
DspLle::DspLle(Core::System& system, bool multithread)
: DspLle(system, system.Memory(), system.CoreTiming(), multithread) {}
DspLle::DspLle(Core::System& system, Memory::MemorySystem& memory, Core::Timing& timing,
bool multithread)
: DspInterface(system), impl(std::make_unique<Impl>(timing, multithread)) {
Teakra::AHBMCallback ahbm;
ahbm.read8 = [&memory](u32 address) -> u8 {
return *memory.GetFCRAMPointer(address - Memory::FCRAM_PADDR);

View file

@ -11,11 +11,17 @@ namespace Core {
class Timing;
}
namespace Memory {
class MemorySystem;
}
namespace AudioCore {
class DspLle final : public DspInterface {
public:
explicit DspLle(Memory::MemorySystem& memory, Core::Timing& timing, bool multithread);
explicit DspLle(Core::System& system, bool multithread);
explicit DspLle(Core::System& system, Memory::MemorySystem& memory, Core::Timing& timing,
bool multithread);
~DspLle() override;
u16 RecvData(u32 register_number) override;