diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt
index a965af2915..5a2747e78d 100644
--- a/src/audio_core/CMakeLists.txt
+++ b/src/audio_core/CMakeLists.txt
@@ -5,6 +5,7 @@ set(SRCS
             hle/filter.cpp
             hle/pipe.cpp
             interpolate.cpp
+            sink_details.cpp
             )
 
 set(HEADERS
@@ -15,7 +16,9 @@ set(HEADERS
             hle/filter.h
             hle/pipe.h
             interpolate.h
+            null_sink.h
             sink.h
+            sink_details.h
             )
 
 include_directories(../../externals/soundtouch/include)
diff --git a/src/audio_core/audio_core.cpp b/src/audio_core/audio_core.cpp
index cbe869a04c..d42249ebd9 100644
--- a/src/audio_core/audio_core.cpp
+++ b/src/audio_core/audio_core.cpp
@@ -2,9 +2,15 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
+#include <memory>
+#include <string>
+
 #include "audio_core/audio_core.h"
 #include "audio_core/hle/dsp.h"
 #include "audio_core/hle/pipe.h"
+#include "audio_core/null_sink.h"
+#include "audio_core/sink.h"
+#include "audio_core/sink_details.h"
 
 #include "core/core_timing.h"
 #include "core/hle/kernel/vm_manager.h"
@@ -28,7 +34,6 @@ static void AudioTickCallback(u64 /*userdata*/, int cycles_late) {
     CoreTiming::ScheduleEvent(audio_frame_ticks - cycles_late, tick_event);
 }
 
-/// Initialise Audio
 void Init() {
     DSP::HLE::Init();
 
@@ -36,7 +41,6 @@ void Init() {
     CoreTiming::ScheduleEvent(audio_frame_ticks, tick_event);
 }
 
-/// Add DSP address spaces to Process's address space.
 void AddAddressSpace(Kernel::VMManager& address_space) {
     auto r0_vma = address_space.MapBackingMemory(DSP::HLE::region0_base, reinterpret_cast<u8*>(&DSP::HLE::g_regions[0]), sizeof(DSP::HLE::SharedMemory), Kernel::MemoryState::IO).MoveFrom();
     address_space.Reprotect(r0_vma, Kernel::VMAPermission::ReadWrite);
@@ -45,10 +49,31 @@ void AddAddressSpace(Kernel::VMManager& address_space) {
     address_space.Reprotect(r1_vma, Kernel::VMAPermission::ReadWrite);
 }
 
-/// Shutdown Audio
+void SelectSink(std::string sink_id) {
+    if (sink_id == "auto") {
+        // Auto-select.
+        // g_sink_details is ordered in terms of desirability, with the best choice at the front.
+        const auto& sink_detail = g_sink_details.front();
+        DSP::HLE::SetSink(sink_detail.factory());
+        return;
+    }
+
+    auto iter = std::find_if(g_sink_details.begin(), g_sink_details.end(), [sink_id](const auto& sink_detail) {
+        return sink_detail.id == sink_id;
+    });
+
+    if (iter == g_sink_details.end()) {
+        LOG_ERROR(Audio, "AudioCore::SelectSink given invalid sink_id");
+        DSP::HLE::SetSink(std::make_unique<NullSink>());
+        return;
+    }
+
+    DSP::HLE::SetSink(iter->factory());
+}
+
 void Shutdown() {
     CoreTiming::UnscheduleEvent(tick_event, 0);
     DSP::HLE::Shutdown();
 }
 
-} //namespace
+} // namespace AudioCore
diff --git a/src/audio_core/audio_core.h b/src/audio_core/audio_core.h
index b349895ea7..f618361f30 100644
--- a/src/audio_core/audio_core.h
+++ b/src/audio_core/audio_core.h
@@ -4,6 +4,8 @@
 
 #pragma once
 
+#include <string>
+
 namespace Kernel {
 class VMManager;
 }
@@ -18,6 +20,9 @@ void Init();
 /// Add DSP address spaces to a Process.
 void AddAddressSpace(Kernel::VMManager& vm_manager);
 
+/// Select the sink to use based on sink id.
+void SelectSink(std::string sink_id);
+
 /// Shutdown Audio Core
 void Shutdown();
 
diff --git a/src/audio_core/hle/dsp.cpp b/src/audio_core/hle/dsp.cpp
index 5759a5b9e4..4d44bd2d93 100644
--- a/src/audio_core/hle/dsp.cpp
+++ b/src/audio_core/hle/dsp.cpp
@@ -2,8 +2,11 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
+#include <memory>
+
 #include "audio_core/hle/dsp.h"
 #include "audio_core/hle/pipe.h"
+#include "audio_core/sink.h"
 
 namespace DSP {
 namespace HLE {
@@ -35,6 +38,8 @@ static SharedMemory& WriteRegion() {
     return g_regions[1 - CurrentRegionIndex()];
 }
 
+static std::unique_ptr<AudioCore::Sink> sink;
+
 void Init() {
     DSP::HLE::ResetPipes();
 }
@@ -46,5 +51,9 @@ bool Tick() {
     return true;
 }
 
+void SetSink(std::unique_ptr<AudioCore::Sink> sink_) {
+    sink = std::move(sink_);
+}
+
 } // namespace HLE
 } // namespace DSP
diff --git a/src/audio_core/hle/dsp.h b/src/audio_core/hle/dsp.h
index f0f1252844..4f2410c27a 100644
--- a/src/audio_core/hle/dsp.h
+++ b/src/audio_core/hle/dsp.h
@@ -6,6 +6,7 @@
 
 #include <array>
 #include <cstddef>
+#include <memory>
 #include <type_traits>
 
 #include "audio_core/hle/common.h"
@@ -15,6 +16,10 @@
 #include "common/common_types.h"
 #include "common/swap.h"
 
+namespace AudioCore {
+class Sink;
+}
+
 namespace DSP {
 namespace HLE {
 
@@ -535,5 +540,11 @@ void Shutdown();
  */
 bool Tick();
 
+/**
+ * Set the output sink. This must be called before calling Tick().
+ * @param sink The sink to which audio will be output to.
+ */
+void SetSink(std::unique_ptr<AudioCore::Sink> sink);
+
 } // namespace HLE
 } // namespace DSP
diff --git a/src/audio_core/null_sink.h b/src/audio_core/null_sink.h
new file mode 100644
index 0000000000..faf0ee4e1e
--- /dev/null
+++ b/src/audio_core/null_sink.h
@@ -0,0 +1,29 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <cstddef>
+
+#include "audio_core/audio_core.h"
+#include "audio_core/sink.h"
+
+namespace AudioCore {
+
+class NullSink final : public Sink {
+public:
+    ~NullSink() override = default;
+
+    unsigned int GetNativeSampleRate() const override {
+        return native_sample_rate;
+    }
+
+    void EnqueueSamples(const std::vector<s16>&) override {}
+
+    size_t SamplesInQueue() const override {
+        return 0;
+    }
+};
+
+} // namespace AudioCore
diff --git a/src/audio_core/sink_details.cpp b/src/audio_core/sink_details.cpp
new file mode 100644
index 0000000000..d2cc741032
--- /dev/null
+++ b/src/audio_core/sink_details.cpp
@@ -0,0 +1,18 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+#include <vector>
+
+#include "audio_core/null_sink.h"
+#include "audio_core/sink_details.h"
+
+namespace AudioCore {
+
+// g_sink_details is ordered in terms of desirability, with the best choice at the top.
+const std::vector<SinkDetails> g_sink_details = {
+    { "null", []() { return std::make_unique<NullSink>(); } },
+};
+
+} // namespace AudioCore
diff --git a/src/audio_core/sink_details.h b/src/audio_core/sink_details.h
new file mode 100644
index 0000000000..4b30cf835f
--- /dev/null
+++ b/src/audio_core/sink_details.h
@@ -0,0 +1,27 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <functional>
+#include <memory>
+#include <vector>
+
+namespace AudioCore {
+
+class Sink;
+
+struct SinkDetails {
+    SinkDetails(const char* id_, std::function<std::unique_ptr<Sink>()> factory_)
+        : id(id_), factory(factory_) {}
+
+    /// Name for this sink.
+    const char* id;
+    /// A method to call to construct an instance of this type of sink.
+    std::function<std::unique_ptr<Sink>()> factory;
+};
+
+extern const std::vector<SinkDetails> g_sink_details;
+
+} // namespace AudioCore
diff --git a/src/citra/config.cpp b/src/citra/config.cpp
index 9e2ecd307f..0d17c80bf2 100644
--- a/src/citra/config.cpp
+++ b/src/citra/config.cpp
@@ -71,6 +71,9 @@ void Config::ReadValues() {
     Settings::values.bg_green = (float)sdl2_config->GetReal("Renderer", "bg_green", 1.0);
     Settings::values.bg_blue  = (float)sdl2_config->GetReal("Renderer", "bg_blue",  1.0);
 
+    // Audio
+    Settings::values.sink_id = sdl2_config->Get("Audio", "output_engine", "auto");
+
     // 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 1f1aa716b8..0e6171736e 100644
--- a/src/citra/default_ini.h
+++ b/src/citra/default_ini.h
@@ -56,6 +56,11 @@ bg_red =
 bg_blue =
 bg_green =
 
+[Audio]
+# Which audio output engine to use.
+# auto (default): Auto-select, null: No audio output
+output_engine =
+
 [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 7dc61fe408..b5bb75537d 100644
--- a/src/citra_qt/config.cpp
+++ b/src/citra_qt/config.cpp
@@ -52,6 +52,10 @@ void Config::ReadValues() {
     Settings::values.bg_blue  = qt_config->value("bg_blue",  1.0).toFloat();
     qt_config->endGroup();
 
+    qt_config->beginGroup("Audio");
+    Settings::values.sink_id = qt_config->value("output_engine", "auto").toString().toStdString();
+    qt_config->endGroup();
+
     qt_config->beginGroup("Data Storage");
     Settings::values.use_virtual_sd = qt_config->value("use_virtual_sd", true).toBool();
     qt_config->endGroup();
@@ -138,6 +142,10 @@ void Config::SaveValues() {
     qt_config->setValue("bg_blue",  (double)Settings::values.bg_blue);
     qt_config->endGroup();
 
+    qt_config->beginGroup("Audio");
+    qt_config->setValue("output_engine", QString::fromStdString(Settings::values.sink_id));
+    qt_config->endGroup();
+
     qt_config->beginGroup("Data Storage");
     qt_config->setValue("use_virtual_sd", Settings::values.use_virtual_sd);
     qt_config->endGroup();
diff --git a/src/core/settings.cpp b/src/core/settings.cpp
index eaf5c8461e..77261eafe2 100644
--- a/src/core/settings.cpp
+++ b/src/core/settings.cpp
@@ -4,6 +4,8 @@
 
 #include "settings.h"
 
+#include "audio_core/audio_core.h"
+
 #include "core/gdbstub/gdbstub.h"
 
 #include "video_core/video_core.h"
@@ -20,6 +22,9 @@ void Apply() {
     VideoCore::g_hw_renderer_enabled = values.use_hw_renderer;
     VideoCore::g_shader_jit_enabled = values.use_shader_jit;
     VideoCore::g_scaled_resolution_enabled = values.use_scaled_resolution;
+
+    AudioCore::SelectSink(values.sink_id);
+
 }
 
 } // namespace
diff --git a/src/core/settings.h b/src/core/settings.h
index d620d84615..04c0a47f91 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -63,6 +63,9 @@ struct Values {
 
     std::string log_filter;
 
+    // Audio
+    std::string sink_id;
+
     // Debugging
     bool use_gdbstub;
     u16 gdbstub_port;