mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	audio_core: Add EnableStretching to interface so that one can toggle stretching on and off
This commit is contained in:
		
							parent
							
								
									0ef4185644
								
							
						
					
					
						commit
						904a319694
					
				
					 4 changed files with 52 additions and 9 deletions
				
			
		|  | @ -71,6 +71,10 @@ void SelectSink(std::string sink_id) { | ||||||
|     DSP::HLE::SetSink(iter->factory()); |     DSP::HLE::SetSink(iter->factory()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void EnableStretching(bool enable) { | ||||||
|  |     DSP::HLE::EnableStretching(enable); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void Shutdown() { | void Shutdown() { | ||||||
|     CoreTiming::UnscheduleEvent(tick_event, 0); |     CoreTiming::UnscheduleEvent(tick_event, 0); | ||||||
|     DSP::HLE::Shutdown(); |     DSP::HLE::Shutdown(); | ||||||
|  |  | ||||||
|  | @ -23,6 +23,9 @@ void AddAddressSpace(Kernel::VMManager& vm_manager); | ||||||
| /// Select the sink to use based on sink id.
 | /// Select the sink to use based on sink id.
 | ||||||
| void SelectSink(std::string sink_id); | void SelectSink(std::string sink_id); | ||||||
| 
 | 
 | ||||||
|  | /// Enable/Disable stretching.
 | ||||||
|  | void EnableStretching(bool enable); | ||||||
|  | 
 | ||||||
| /// Shutdown Audio Core
 | /// Shutdown Audio Core
 | ||||||
| void Shutdown(); | void Shutdown(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -85,13 +85,45 @@ static StereoFrame16 GenerateCurrentFrame() { | ||||||
| 
 | 
 | ||||||
| // Audio output
 | // Audio output
 | ||||||
| 
 | 
 | ||||||
|  | static bool perform_time_stretching = true; | ||||||
| static std::unique_ptr<AudioCore::Sink> sink; | static std::unique_ptr<AudioCore::Sink> sink; | ||||||
| static AudioCore::TimeStretcher time_stretcher; | static AudioCore::TimeStretcher time_stretcher; | ||||||
| 
 | 
 | ||||||
|  | static void FlushResidualStretcherAudio() { | ||||||
|  |     time_stretcher.Flush(); | ||||||
|  |     while (true) { | ||||||
|  |         std::vector<s16> residual_audio = time_stretcher.Process(sink->SamplesInQueue()); | ||||||
|  |         if (residual_audio.empty()) | ||||||
|  |             break; | ||||||
|  |         sink->EnqueueSamples(residual_audio.data(), residual_audio.size() / 2); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static void OutputCurrentFrame(const StereoFrame16& frame) { | static void OutputCurrentFrame(const StereoFrame16& frame) { | ||||||
|     time_stretcher.AddSamples(&frame[0][0], frame.size()); |     if (perform_time_stretching) { | ||||||
|     std::vector<s16> stretched_samples = time_stretcher.Process(sink->SamplesInQueue()); |         time_stretcher.AddSamples(&frame[0][0], frame.size()); | ||||||
|     sink->EnqueueSamples(stretched_samples.data(), stretched_samples.size() / 2); |         std::vector<s16> stretched_samples = time_stretcher.Process(sink->SamplesInQueue()); | ||||||
|  |         sink->EnqueueSamples(stretched_samples.data(), stretched_samples.size() / 2); | ||||||
|  |     } else { | ||||||
|  |         constexpr size_t maximum_sample_latency = 1024; // about 32 miliseconds
 | ||||||
|  |         if (sink->SamplesInQueue() > maximum_sample_latency) { | ||||||
|  |             // This can occur if we're running too fast and samples are starting to back up.
 | ||||||
|  |             // Just drop the samples.
 | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         sink->EnqueueSamples(&frame[0][0], frame.size()); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void EnableStretching(bool enable) { | ||||||
|  |     if (perform_time_stretching == enable) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     if (!enable) { | ||||||
|  |         FlushResidualStretcherAudio(); | ||||||
|  |     } | ||||||
|  |     perform_time_stretching = enable; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Public Interface
 | // Public Interface
 | ||||||
|  | @ -112,12 +144,8 @@ void Init() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Shutdown() { | void Shutdown() { | ||||||
|     time_stretcher.Flush(); |     if (perform_time_stretching) { | ||||||
|     while (true) { |         FlushResidualStretcherAudio(); | ||||||
|         std::vector<s16> residual_audio = time_stretcher.Process(sink->SamplesInQueue()); |  | ||||||
|         if (residual_audio.empty()) |  | ||||||
|             break; |  | ||||||
|         sink->EnqueueSamples(residual_audio); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -544,5 +544,13 @@ bool Tick(); | ||||||
|  */ |  */ | ||||||
| void SetSink(std::unique_ptr<AudioCore::Sink> sink); | void SetSink(std::unique_ptr<AudioCore::Sink> sink); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * Enables/Disables audio-stretching. | ||||||
|  |  * Audio stretching is an enhancement that stretches audio to match emulation | ||||||
|  |  * speed to prevent stuttering at the cost of some audio latency. | ||||||
|  |  * @param enable true to enable, false to disable. | ||||||
|  |  */ | ||||||
|  | void EnableStretching(bool enable); | ||||||
|  | 
 | ||||||
| } // namespace HLE
 | } // namespace HLE
 | ||||||
| } // namespace DSP
 | } // namespace DSP
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue