summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar MerryMage2016-08-31 16:56:30 +0100
committerGravatar MerryMage2016-08-31 16:56:30 +0100
commit904a31969469a5ecff7eacfddc8541ea5996dcdf (patch)
tree369e91b89e1f4b2aef805b9f85c734d377ce631e /src
parentsink: Change EnqueueSamples to take a pointer to a buffer instead of a std::v... (diff)
downloadyuzu-904a31969469a5ecff7eacfddc8541ea5996dcdf.tar.gz
yuzu-904a31969469a5ecff7eacfddc8541ea5996dcdf.tar.xz
yuzu-904a31969469a5ecff7eacfddc8541ea5996dcdf.zip
audio_core: Add EnableStretching to interface so that one can toggle stretching on and off
Diffstat (limited to 'src')
-rw-r--r--src/audio_core/audio_core.cpp4
-rw-r--r--src/audio_core/audio_core.h3
-rw-r--r--src/audio_core/hle/dsp.cpp46
-rw-r--r--src/audio_core/hle/dsp.h8
4 files changed, 52 insertions, 9 deletions
diff --git a/src/audio_core/audio_core.cpp b/src/audio_core/audio_core.cpp
index d42249ebd..8e19ec0c4 100644
--- a/src/audio_core/audio_core.cpp
+++ b/src/audio_core/audio_core.cpp
@@ -71,6 +71,10 @@ void SelectSink(std::string sink_id) {
71 DSP::HLE::SetSink(iter->factory()); 71 DSP::HLE::SetSink(iter->factory());
72} 72}
73 73
74void EnableStretching(bool enable) {
75 DSP::HLE::EnableStretching(enable);
76}
77
74void Shutdown() { 78void Shutdown() {
75 CoreTiming::UnscheduleEvent(tick_event, 0); 79 CoreTiming::UnscheduleEvent(tick_event, 0);
76 DSP::HLE::Shutdown(); 80 DSP::HLE::Shutdown();
diff --git a/src/audio_core/audio_core.h b/src/audio_core/audio_core.h
index f618361f3..7e678aba5 100644
--- a/src/audio_core/audio_core.h
+++ b/src/audio_core/audio_core.h
@@ -23,6 +23,9 @@ void AddAddressSpace(Kernel::VMManager& vm_manager);
23/// Select the sink to use based on sink id. 23/// Select the sink to use based on sink id.
24void SelectSink(std::string sink_id); 24void SelectSink(std::string sink_id);
25 25
26/// Enable/Disable stretching.
27void EnableStretching(bool enable);
28
26/// Shutdown Audio Core 29/// Shutdown Audio Core
27void Shutdown(); 30void Shutdown();
28 31
diff --git a/src/audio_core/hle/dsp.cpp b/src/audio_core/hle/dsp.cpp
index a195bc74c..0cddeb82a 100644
--- a/src/audio_core/hle/dsp.cpp
+++ b/src/audio_core/hle/dsp.cpp
@@ -85,13 +85,45 @@ static StereoFrame16 GenerateCurrentFrame() {
85 85
86// Audio output 86// Audio output
87 87
88static bool perform_time_stretching = true;
88static std::unique_ptr<AudioCore::Sink> sink; 89static std::unique_ptr<AudioCore::Sink> sink;
89static AudioCore::TimeStretcher time_stretcher; 90static AudioCore::TimeStretcher time_stretcher;
90 91
92static void FlushResidualStretcherAudio() {
93 time_stretcher.Flush();
94 while (true) {
95 std::vector<s16> residual_audio = time_stretcher.Process(sink->SamplesInQueue());
96 if (residual_audio.empty())
97 break;
98 sink->EnqueueSamples(residual_audio.data(), residual_audio.size() / 2);
99 }
100}
101
91static void OutputCurrentFrame(const StereoFrame16& frame) { 102static void OutputCurrentFrame(const StereoFrame16& frame) {
92 time_stretcher.AddSamples(&frame[0][0], frame.size()); 103 if (perform_time_stretching) {
93 std::vector<s16> stretched_samples = time_stretcher.Process(sink->SamplesInQueue()); 104 time_stretcher.AddSamples(&frame[0][0], frame.size());
94 sink->EnqueueSamples(stretched_samples.data(), stretched_samples.size() / 2); 105 std::vector<s16> stretched_samples = time_stretcher.Process(sink->SamplesInQueue());
106 sink->EnqueueSamples(stretched_samples.data(), stretched_samples.size() / 2);
107 } else {
108 constexpr size_t maximum_sample_latency = 1024; // about 32 miliseconds
109 if (sink->SamplesInQueue() > maximum_sample_latency) {
110 // This can occur if we're running too fast and samples are starting to back up.
111 // Just drop the samples.
112 return;
113 }
114
115 sink->EnqueueSamples(&frame[0][0], frame.size());
116 }
117}
118
119void EnableStretching(bool enable) {
120 if (perform_time_stretching == enable)
121 return;
122
123 if (!enable) {
124 FlushResidualStretcherAudio();
125 }
126 perform_time_stretching = enable;
95} 127}
96 128
97// Public Interface 129// Public Interface
@@ -112,12 +144,8 @@ void Init() {
112} 144}
113 145
114void Shutdown() { 146void Shutdown() {
115 time_stretcher.Flush(); 147 if (perform_time_stretching) {
116 while (true) { 148 FlushResidualStretcherAudio();
117 std::vector<s16> residual_audio = time_stretcher.Process(sink->SamplesInQueue());
118 if (residual_audio.empty())
119 break;
120 sink->EnqueueSamples(residual_audio);
121 } 149 }
122} 150}
123 151
diff --git a/src/audio_core/hle/dsp.h b/src/audio_core/hle/dsp.h
index 9275cd7de..565f20b6f 100644
--- a/src/audio_core/hle/dsp.h
+++ b/src/audio_core/hle/dsp.h
@@ -544,5 +544,13 @@ bool Tick();
544 */ 544 */
545void SetSink(std::unique_ptr<AudioCore::Sink> sink); 545void SetSink(std::unique_ptr<AudioCore::Sink> sink);
546 546
547/**
548 * Enables/Disables audio-stretching.
549 * Audio stretching is an enhancement that stretches audio to match emulation
550 * speed to prevent stuttering at the cost of some audio latency.
551 * @param enable true to enable, false to disable.
552 */
553void EnableStretching(bool enable);
554
547} // namespace HLE 555} // namespace HLE
548} // namespace DSP 556} // namespace DSP