// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin // SPDX-License-Identifier: CC-BY-NC-ND-4.0 #include "audio_stream.h" #include "translation.h" #include "common/error.h" AudioStream::AudioStream() = default; AudioStream::~AudioStream() = default; AudioStream::DeviceInfo::DeviceInfo(std::string name_, std::string display_name_, u32 minimum_latency_) : name(std::move(name_)), display_name(std::move(display_name_)), minimum_latency_frames(minimum_latency_) { } AudioStream::DeviceInfo::~DeviceInfo() = default; static constexpr const std::array s_backend_names = { // clang-format off "Null", #ifndef __ANDROID__ "Cubeb", "SDL", #endif #ifdef _WIN32 "XAudio2", #endif #ifdef __ANDROID__ "AAudio", "OpenSLES", #endif // clang-format on }; static constexpr const std::array s_backend_display_names = { // clang-format off TRANSLATE_DISAMBIG_NOOP("Settings", "Null (No Output)", "AudioBackend"), #ifndef __ANDROID__ TRANSLATE_DISAMBIG_NOOP("Settings", "Cubeb", "AudioBackend"), TRANSLATE_DISAMBIG_NOOP("Settings", "SDL", "AudioBackend"), #endif #ifdef _WIN32 TRANSLATE_DISAMBIG_NOOP("Settings", "XAudio2", "AudioBackend"), #endif #ifdef __ANDROID__ "AAudio", "OpenSL ES", #endif // clang-format on }; std::optional AudioStream::ParseBackendName(std::string_view str) { int index = 0; for (const char* name : s_backend_names) { if (str == name) return static_cast(index); index++; } return std::nullopt; } const char* AudioStream::GetBackendName(AudioBackend backend) { return s_backend_names[static_cast(backend)]; } const char* AudioStream::GetBackendDisplayName(AudioBackend backend) { return Host::TranslateToCString("Settings", s_backend_display_names[static_cast(backend)], "AudioBackend"); } u32 AudioStream::FramesToMS(u32 sample_rate, u32 frames) { return (frames * 1000) / sample_rate; } std::vector> AudioStream::GetDriverNames(AudioBackend backend) { std::vector> ret; switch (backend) { #ifndef __ANDROID__ case AudioBackend::Cubeb: ret = GetCubebDriverNames(); break; #endif default: break; } return ret; } std::vector AudioStream::GetOutputDevices(AudioBackend backend, std::string_view driver, u32 sample_rate) { std::vector ret; switch (backend) { #ifndef __ANDROID__ case AudioBackend::Cubeb: ret = GetCubebOutputDevices(driver, sample_rate); break; #endif #ifdef _WIN32 case AudioBackend::XAudio2: ret = GetXAudio2OutputDevices(sample_rate); break; #endif default: break; } return ret; } std::unique_ptr AudioStream::CreateStream(AudioBackend backend, u32 sample_rate, u32 channels, u32 output_latency_frames, bool output_latency_minimal, std::string_view driver_name, std::string_view device_name, AudioStreamSource* source, bool auto_start, Error* error) { switch (backend) { #ifndef __ANDROID__ case AudioBackend::Cubeb: return CreateCubebAudioStream(sample_rate, channels, output_latency_frames, output_latency_minimal, driver_name, device_name, source, auto_start, error); case AudioBackend::SDL: return CreateSDLAudioStream(sample_rate, channels, output_latency_frames, output_latency_minimal, source, auto_start, error); #endif #ifdef _WIN32 case AudioBackend::XAudio2: return CreateXAudio2AudioStream(sample_rate, channels, output_latency_frames, output_latency_minimal, device_name, source, auto_start, error); #endif #ifdef __ANDROID__ case AudioBackend::AAudio: return CreateAAudioAudioStream(sample_rate, channels, output_latency_frames, output_latency_minimal, source, auto_start, error); case AudioBackend::OpenSLES: return CreateOpenSLESAudioStream(sample_rate, channels, output_latency_frames, output_latency_minimal, source, auto_start, error); #endif default: Error::SetStringView(error, "Unknown audio backend."); return nullptr; } }