mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	audio_core: Only perform audio stretching if below full speed. (#7201)
This commit is contained in:
		
							parent
							
								
									c0ecdb689d
								
							
						
					
					
						commit
						670e9936a4
					
				
					 13 changed files with 83 additions and 52 deletions
				
			
		|  | @ -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); | ||||
|  |  | |||
|  | @ -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{}; | ||||
|  |  | |||
|  | @ -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) { | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue