diff --git a/cpmfile.json b/cpmfile.json
index ce6275fb99..7c1928b31a 100644
--- a/cpmfile.json
+++ b/cpmfile.json
@@ -179,12 +179,6 @@
"repo": "eden-emulator/oaknut",
"version": "v2.0.3"
},
- "oboe": {
- "bundled": true,
- "hash": "ce4011afe7345370d4ead3b891cd69a5ef224b129535783586c0ca75051d303ed446e6c7f10bde8da31fff58d6e307f1732a3ffd03b249f9ef1fd48fd4132715",
- "repo": "google/oboe",
- "version": "1.10.0"
- },
"openssl": {
"hash": "29002ce50cb95a4f4f1d0e9d3f684401fbd4eac34203dc2eef3b6334af5d44aa46bf788b63a6f5c139c383eafb7269ae87a58a9a3ad5912903b9773e545ccc0a",
"min_version": "3.0.0",
diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt
index e89a766106..29c0997fe1 100644
--- a/externals/CMakeLists.txt
+++ b/externals/CMakeLists.txt
@@ -388,13 +388,6 @@ if (YUZU_CRASH_DUMPS AND NOT TARGET libbreakpad_client)
endif()
endif()
-# oboe
-if (ANDROID)
- AddJsonPackage(oboe)
-
- add_library(oboe::oboe ALIAS oboe)
-endif()
-
if (APPLE)
# moltenvk
if (NOT YUZU_USE_BUNDLED_MOLTENVK)
diff --git a/src/android/app/src/main/res/values-fa/strings.xml b/src/android/app/src/main/res/values-fa/strings.xml
index 98b94d166d..562cfdfe7c 100644
--- a/src/android/app/src/main/res/values-fa/strings.xml
+++ b/src/android/app/src/main/res/values-fa/strings.xml
@@ -799,10 +799,6 @@
روشن
تاریک
-
- oboe
- cubeb
-
x2
x4
diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml
index b1c0a98a61..1ac993e8b3 100644
--- a/src/android/app/src/main/res/values/arrays.xml
+++ b/src/android/app/src/main/res/values/arrays.xml
@@ -465,14 +465,14 @@
- @string/auto
- - @string/oboe
- @string/cubeb
+ - @string/sdl3
- @string/string_null
- 0
- - 4
- 1
+ - 2
- 3
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index 3f6d1889ff..107c94b97e 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -1240,7 +1240,7 @@
Dark
- oboe
+ sdl3
cubeb
diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt
index b186edaab4..ac4fb8b84f 100644
--- a/src/audio_core/CMakeLists.txt
+++ b/src/audio_core/CMakeLists.txt
@@ -238,20 +238,10 @@ if (ENABLE_CUBEB)
target_compile_definitions(audio_core PRIVATE HAVE_CUBEB=1)
endif()
-if(ANDROID)
- target_sources(audio_core PRIVATE
- sink/oboe_sink.cpp
- sink/oboe_sink.h)
-
- target_link_libraries(audio_core PRIVATE oboe)
- target_compile_definitions(audio_core PUBLIC HAVE_OBOE)
-else()
- target_sources(audio_core PRIVATE
- sink/sdl3_sink.cpp
- sink/sdl3_sink.h)
-
- target_link_libraries(audio_core PRIVATE SDL3::SDL3)
- target_compile_definitions(audio_core PRIVATE HAVE_SDL3)
-endif()
+target_sources(audio_core PRIVATE
+ sink/sdl3_sink.cpp
+ sink/sdl3_sink.h)
+target_link_libraries(audio_core PRIVATE SDL3::SDL3)
+target_compile_definitions(audio_core PRIVATE HAVE_SDL3)
create_target_directory_groups(audio_core)
diff --git a/src/audio_core/sink/oboe_sink.cpp b/src/audio_core/sink/oboe_sink.cpp
deleted file mode 100644
index d1ead7d880..0000000000
--- a/src/audio_core/sink/oboe_sink.cpp
+++ /dev/null
@@ -1,230 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include
-#include
-
-#include
-
-#include "audio_core/common/common.h"
-#include "audio_core/sink/oboe_sink.h"
-#include "audio_core/sink/sink_stream.h"
-#include "common/logging.h"
-#include "common/scope_exit.h"
-#include "core/core.h"
-
-namespace AudioCore::Sink {
-
-class OboeSinkStream final : public SinkStream,
- public oboe::AudioStreamDataCallback,
- public oboe::AudioStreamErrorCallback {
-public:
- explicit OboeSinkStream(Core::System& system_, StreamType type_, const std::string& name_,
- u32 system_channels_)
- : SinkStream(system_, type_) {
- name = name_;
- system_channels = system_channels_;
-
- this->OpenStream();
- }
-
- ~OboeSinkStream() override {
- LOG_INFO(Audio_Sink, "Destroyed Oboe stream");
- }
-
- void Finalize() override {
- this->Stop();
- m_stream.reset();
- }
-
- void Start(bool resume = false) override {
- if (!m_stream || !paused) {
- return;
- }
-
- paused = false;
-
- if (m_stream->start() != oboe::Result::OK) {
- LOG_CRITICAL(Audio_Sink, "Error starting Oboe stream");
- }
- }
-
- void Stop() override {
- if (!m_stream || paused) {
- return;
- }
-
- this->SignalPause();
-
- if (m_stream->stop() != oboe::Result::OK) {
- LOG_CRITICAL(Audio_Sink, "Error stopping Oboe stream");
- }
- }
-
-public:
- static s32 QueryChannelCount(oboe::Direction direction) {
- std::shared_ptr temp_stream;
- oboe::AudioStreamBuilder builder;
-
- const auto result = ConfigureBuilder(builder, direction)->openStream(temp_stream);
- if (result == oboe::Result::OK) {
- return temp_stream->getChannelCount() >= 6 ? 6 : 2;
- }
-
- LOG_ERROR(Audio_Sink, "Failed to open {} stream. Using default channel count 2",
- direction == oboe::Direction::Output ? "output" : "input");
- return 2;
- }
-
-protected:
- oboe::DataCallbackResult onAudioReady(oboe::AudioStream*, void* audio_data,
- s32 num_buffer_frames) override {
- const size_t num_channels = this->GetDeviceChannels();
- const size_t frame_size = num_channels;
- const size_t num_frames = static_cast(num_buffer_frames);
-
- if (type == StreamType::In) {
- std::span input_buffer{reinterpret_cast(audio_data),
- num_frames * frame_size};
- this->ProcessAudioIn(input_buffer, num_frames);
- } else {
- std::span output_buffer{reinterpret_cast(audio_data),
- num_frames * frame_size};
- this->ProcessAudioOutAndRender(output_buffer, num_frames);
- }
-
- return oboe::DataCallbackResult::Continue;
- }
-
- void onErrorAfterClose(oboe::AudioStream*, oboe::Result) override {
- LOG_INFO(Audio_Sink, "Audio stream closed, reinitializing");
-
- if (this->OpenStream()) {
- m_stream->start();
- }
- }
-
-private:
- static oboe::AudioStreamBuilder* ConfigureBuilder(oboe::AudioStreamBuilder& builder,
- oboe::Direction direction) {
- // TODO: investigate callback delay issues when using AAudio
- return builder.setPerformanceMode(oboe::PerformanceMode::LowLatency)
- ->setAudioApi(oboe::AudioApi::OpenSLES)
- ->setDirection(direction)
- ->setSampleRate(TargetSampleRate)
- ->setSampleRateConversionQuality(oboe::SampleRateConversionQuality::High)
- ->setFormat(oboe::AudioFormat::I16)
- ->setFormatConversionAllowed(true)
- ->setUsage(oboe::Usage::Game)
- ->setBufferCapacityInFrames(TargetSampleCount * 2);
- }
-
- bool OpenStream() {
- const auto direction = [&]() {
- switch (type) {
- case StreamType::In:
- return oboe::Direction::Input;
- case StreamType::Out:
- case StreamType::Render:
- return oboe::Direction::Output;
- default:
- ASSERT(false);
- return oboe::Direction::Output;
- }
- }();
-
- const auto expected_channels = QueryChannelCount(direction);
- const auto expected_mask = [&]() {
- switch (expected_channels) {
- case 1:
- return oboe::ChannelMask::Mono;
- case 2:
- return oboe::ChannelMask::Stereo;
- case 6:
- return oboe::ChannelMask::CM5Point1;
- default:
- ASSERT(false);
- return oboe::ChannelMask::Unspecified;
- }
- }();
-
- oboe::AudioStreamBuilder builder;
- const auto result = ConfigureBuilder(builder, direction)
- ->setChannelCount(expected_channels)
- ->setChannelMask(expected_mask)
- ->setChannelConversionAllowed(true)
- ->setDataCallback(this)
- ->setErrorCallback(this)
- ->openStream(m_stream);
- ASSERT(result == oboe::Result::OK);
- return result == oboe::Result::OK && this->SetStreamProperties();
- }
-
- bool SetStreamProperties() {
- ASSERT(m_stream);
-
- m_stream->setBufferSizeInFrames(TargetSampleCount * 2);
- device_channels = m_stream->getChannelCount();
-
- const auto sample_rate = m_stream->getSampleRate();
- const auto buffer_capacity = m_stream->getBufferCapacityInFrames();
- const auto stream_backend =
- m_stream->getAudioApi() == oboe::AudioApi::AAudio ? "AAudio" : "OpenSLES";
-
- LOG_INFO(Audio_Sink, "Opened Oboe {} stream with {} channels sample rate {} capacity {}",
- stream_backend, device_channels, sample_rate, buffer_capacity);
-
- return true;
- }
-
- std::shared_ptr m_stream{};
-};
-
-OboeSink::OboeSink() {
- // TODO: This is not generally knowable
- // The channel count is distinct based on direction and can change
- device_channels = OboeSinkStream::QueryChannelCount(oboe::Direction::Output);
-}
-
-OboeSink::~OboeSink() = default;
-
-SinkStream* OboeSink::AcquireSinkStream(Core::System& system, u32 system_channels,
- const std::string& name, StreamType type) {
- SinkStreamPtr& stream = sink_streams.emplace_back(
- std::make_unique(system, type, name, system_channels));
-
- return stream.get();
-}
-
-void OboeSink::CloseStream(SinkStream* to_remove) {
- sink_streams.remove_if([&](auto& stream) { return stream.get() == to_remove; });
-}
-
-void OboeSink::CloseStreams() {
- sink_streams.clear();
-}
-
-f32 OboeSink::GetDeviceVolume() const {
- if (sink_streams.empty()) {
- return 1.0f;
- }
-
- return sink_streams.front()->GetDeviceVolume();
-}
-
-void OboeSink::SetDeviceVolume(f32 volume) {
- for (auto& stream : sink_streams) {
- stream->SetDeviceVolume(volume);
- }
-}
-
-void OboeSink::SetSystemVolume(f32 volume) {
- for (auto& stream : sink_streams) {
- stream->SetSystemVolume(volume);
- }
-}
-
-} // namespace AudioCore::Sink
diff --git a/src/audio_core/sink/oboe_sink.h b/src/audio_core/sink/oboe_sink.h
deleted file mode 100644
index 8f6f54ab53..0000000000
--- a/src/audio_core/sink/oboe_sink.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include
-#include
-
-#include "audio_core/sink/sink.h"
-
-namespace Core {
-class System;
-}
-
-namespace AudioCore::Sink {
-class SinkStream;
-
-class OboeSink final : public Sink {
-public:
- explicit OboeSink();
- ~OboeSink() override;
-
- /**
- * Create a new sink stream.
- *
- * @param system - Core system.
- * @param system_channels - Number of channels the audio system expects.
- * May differ from the device's channel count.
- * @param name - Name of this stream.
- * @param type - Type of this stream, render/in/out.
- *
- * @return A pointer to the created SinkStream
- */
- SinkStream* AcquireSinkStream(Core::System& system, u32 system_channels,
- const std::string& name, StreamType type) override;
-
- /**
- * Close a given stream.
- *
- * @param stream - The stream to close.
- */
- void CloseStream(SinkStream* stream) override;
-
- /**
- * Close all streams.
- */
- void CloseStreams() override;
-
- /**
- * Get the device volume. Set from calls to the IAudioDevice service.
- *
- * @return Volume of the device.
- */
- f32 GetDeviceVolume() const override;
-
- /**
- * Set the device volume. Set from calls to the IAudioDevice service.
- *
- * @param volume - New volume of the device.
- */
- void SetDeviceVolume(f32 volume) override;
-
- /**
- * Set the system volume. Comes from the audio system using this stream.
- *
- * @param volume - New volume of the system.
- */
- void SetSystemVolume(f32 volume) override;
-
-private:
- /// List of streams managed by this sink
- std::list sink_streams{};
-};
-
-} // namespace AudioCore::Sink