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) {
     DSP::HLE::SetSink(iter->factory());
 }
 
+void EnableStretching(bool enable) {
+    DSP::HLE::EnableStretching(enable);
+}
+
 void Shutdown() {
     CoreTiming::UnscheduleEvent(tick_event, 0);
     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);
 /// Select the sink to use based on sink id.
 void SelectSink(std::string sink_id);
 
+/// Enable/Disable stretching.
+void EnableStretching(bool enable);
+
 /// Shutdown Audio Core
 void Shutdown();
 
diff --git a/src/audio_core/hle/dsp.cpp b/src/audio_core/hle/dsp.cpp
index 0640e1eff..0cddeb82a 100644
--- a/src/audio_core/hle/dsp.cpp
+++ b/src/audio_core/hle/dsp.cpp
@@ -85,12 +85,45 @@ static StereoFrame16 GenerateCurrentFrame() {
 
 // Audio output
 
+static bool perform_time_stretching = true;
 static std::unique_ptr<AudioCore::Sink> sink;
 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) {
-    time_stretcher.AddSamples(&frame[0][0], frame.size());
-    sink->EnqueueSamples(time_stretcher.Process(sink->SamplesInQueue()));
+    if (perform_time_stretching) {
+        time_stretcher.AddSamples(&frame[0][0], frame.size());
+        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
@@ -111,12 +144,8 @@ void Init() {
 }
 
 void Shutdown() {
-    time_stretcher.Flush();
-    while (true) {
-        std::vector<s16> residual_audio = time_stretcher.Process(sink->SamplesInQueue());
-        if (residual_audio.empty())
-            break;
-        sink->EnqueueSamples(residual_audio);
+    if (perform_time_stretching) {
+        FlushResidualStretcherAudio();
     }
 }
 
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();
  */
 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 DSP
diff --git a/src/audio_core/null_sink.h b/src/audio_core/null_sink.h
index faf0ee4e1..9931c4778 100644
--- a/src/audio_core/null_sink.h
+++ b/src/audio_core/null_sink.h
@@ -19,7 +19,7 @@ public:
         return native_sample_rate;
     }
 
-    void EnqueueSamples(const std::vector<s16>&) override {}
+    void EnqueueSamples(const s16*, size_t) override {}
 
     size_t SamplesInQueue() const override {
         return 0;
diff --git a/src/audio_core/sdl2_sink.cpp b/src/audio_core/sdl2_sink.cpp
index dc75c04ee..311dd5b59 100644
--- a/src/audio_core/sdl2_sink.cpp
+++ b/src/audio_core/sdl2_sink.cpp
@@ -71,14 +71,12 @@ unsigned int SDL2Sink::GetNativeSampleRate() const {
     return impl->sample_rate;
 }
 
-void SDL2Sink::EnqueueSamples(const std::vector<s16>& samples) {
+void SDL2Sink::EnqueueSamples(const s16* samples, size_t sample_count) {
     if (impl->audio_device_id <= 0)
         return;
 
-    ASSERT_MSG(samples.size() % 2 == 0, "Samples must be in interleaved stereo PCM16 format (size must be a multiple of two)");
-
     SDL_LockAudioDevice(impl->audio_device_id);
-    impl->queue.emplace_back(samples);
+    impl->queue.emplace_back(samples, samples + sample_count * 2);
     SDL_UnlockAudioDevice(impl->audio_device_id);
 }
 
diff --git a/src/audio_core/sdl2_sink.h b/src/audio_core/sdl2_sink.h
index 0f296b673..b13827214 100644
--- a/src/audio_core/sdl2_sink.h
+++ b/src/audio_core/sdl2_sink.h
@@ -18,7 +18,7 @@ public:
 
     unsigned int GetNativeSampleRate() const override;
 
-    void EnqueueSamples(const std::vector<s16>& samples) override;
+    void EnqueueSamples(const s16* samples, size_t sample_count) override;
 
     size_t SamplesInQueue() const override;
 
diff --git a/src/audio_core/sink.h b/src/audio_core/sink.h
index 1c881c3d2..a06fc3dcc 100644
--- a/src/audio_core/sink.h
+++ b/src/audio_core/sink.h
@@ -23,9 +23,10 @@ public:
 
     /**
      * Feed stereo samples to sink.
-     * @param samples Samples in interleaved stereo PCM16 format. Size of vector must be multiple of two.
+     * @param samples Samples in interleaved stereo PCM16 format.
+     * @param sample_count Number of samples.
      */
-    virtual void EnqueueSamples(const std::vector<s16>& samples) = 0;
+    virtual void EnqueueSamples(const s16* samples, size_t sample_count) = 0;
 
     /// Samples enqueued that have not been played yet.
     virtual std::size_t SamplesInQueue() const = 0;
diff --git a/src/citra/config.cpp b/src/citra/config.cpp
index e832ec58d..f48386b9c 100644
--- a/src/citra/config.cpp
+++ b/src/citra/config.cpp
@@ -78,6 +78,7 @@ void Config::ReadValues() {
 
     // Audio
     Settings::values.sink_id = sdl2_config->Get("Audio", "output_engine", "auto");
+    Settings::values.enable_audio_stretching = sdl2_config->GetBoolean("Audio", "enable_audio_stretching", true);
 
     // Data Storage
     Settings::values.use_virtual_sd = sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true);
diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h
index 6249ef9e2..5b8ca12a0 100644
--- a/src/citra/default_ini.h
+++ b/src/citra/default_ini.h
@@ -66,6 +66,12 @@ bg_green =
 # auto (default): Auto-select, null: No audio output, sdl2: SDL2 (if available)
 output_engine =
 
+# Whether or not to enable the audio-stretching post-processing effect.
+# This effect adjusts audio speed to match emulation speed and helps prevent audio stutter,
+# at the cost of increasing audio latency.
+# 0: No, 1 (default): Yes
+enable_audio_stretching =
+
 [Data Storage]
 # Whether to create a virtual SD card.
 # 1 (default): Yes, 0: No
diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp
index 93c6a6e41..ff3bfe1bd 100644
--- a/src/citra_qt/config.cpp
+++ b/src/citra_qt/config.cpp
@@ -56,6 +56,7 @@ void Config::ReadValues() {
 
     qt_config->beginGroup("Audio");
     Settings::values.sink_id = qt_config->value("output_engine", "auto").toString().toStdString();
+    Settings::values.enable_audio_stretching = qt_config->value("enable_audio_stretching", true).toBool();
     qt_config->endGroup();
 
     qt_config->beginGroup("Data Storage");
@@ -148,6 +149,7 @@ void Config::SaveValues() {
 
     qt_config->beginGroup("Audio");
     qt_config->setValue("output_engine", QString::fromStdString(Settings::values.sink_id));
+    qt_config->setValue("enable_audio_stretching", Settings::values.enable_audio_stretching);
     qt_config->endGroup();
 
     qt_config->beginGroup("Data Storage");
diff --git a/src/citra_qt/configure_audio.cpp b/src/citra_qt/configure_audio.cpp
index cedfa2f2a..7100be158 100644
--- a/src/citra_qt/configure_audio.cpp
+++ b/src/citra_qt/configure_audio.cpp
@@ -36,9 +36,12 @@ void ConfigureAudio::setConfiguration() {
         }
     }
     ui->output_sink_combo_box->setCurrentIndex(new_sink_index);
+
+    ui->toggle_audio_stretching->setChecked(Settings::values.enable_audio_stretching);
 }
 
 void ConfigureAudio::applyConfiguration() {
     Settings::values.sink_id = ui->output_sink_combo_box->itemText(ui->output_sink_combo_box->currentIndex()).toStdString();
+    Settings::values.enable_audio_stretching = ui->toggle_audio_stretching->isChecked();
     Settings::Apply();
 }
diff --git a/src/citra_qt/configure_audio.ui b/src/citra_qt/configure_audio.ui
index d7f6946ca..3e2b4635f 100644
--- a/src/citra_qt/configure_audio.ui
+++ b/src/citra_qt/configure_audio.ui
@@ -25,6 +25,16 @@
         </item>
        </layout>
       </item>
+      <item>
+       <widget class="QCheckBox" name="toggle_audio_stretching">
+        <property name="text">
+         <string>Enable audio stretching</string>
+        </property>
+        <property name="toolTip">
+         <string>This post-processing effect adjusts audio speed to match emulation speed and helps prevent audio stutter. This however increases audio latency.</string>
+        </property>
+       </widget>
+      </item>
      </layout>
     </widget>
    </item>
diff --git a/src/core/settings.cpp b/src/core/settings.cpp
index 77261eafe..1b6733a79 100644
--- a/src/core/settings.cpp
+++ b/src/core/settings.cpp
@@ -24,6 +24,7 @@ void Apply() {
     VideoCore::g_scaled_resolution_enabled = values.use_scaled_resolution;
 
     AudioCore::SelectSink(values.sink_id);
+    AudioCore::EnableStretching(values.enable_audio_stretching);
 
 }
 
diff --git a/src/core/settings.h b/src/core/settings.h
index f95e62390..0962a4ecf 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -81,6 +81,7 @@ struct Values {
 
     // Audio
     std::string sink_id;
+    bool enable_audio_stretching;
 
     // Debugging
     bool use_gdbstub;