mirror of https://github.com/stenzek/duckstation
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
4.4 KiB
C++
159 lines
4.4 KiB
C++
// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin <stenzek@gmail.com>
|
|
// 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<AudioBackend> AudioStream::ParseBackendName(std::string_view str)
|
|
{
|
|
int index = 0;
|
|
for (const char* name : s_backend_names)
|
|
{
|
|
if (str == name)
|
|
return static_cast<AudioBackend>(index);
|
|
|
|
index++;
|
|
}
|
|
|
|
return std::nullopt;
|
|
}
|
|
|
|
const char* AudioStream::GetBackendName(AudioBackend backend)
|
|
{
|
|
return s_backend_names[static_cast<int>(backend)];
|
|
}
|
|
|
|
const char* AudioStream::GetBackendDisplayName(AudioBackend backend)
|
|
{
|
|
return Host::TranslateToCString("Settings", s_backend_display_names[static_cast<int>(backend)], "AudioBackend");
|
|
}
|
|
|
|
u32 AudioStream::FramesToMS(u32 sample_rate, u32 frames)
|
|
{
|
|
return (frames * 1000) / sample_rate;
|
|
}
|
|
|
|
std::vector<std::pair<std::string, std::string>> AudioStream::GetDriverNames(AudioBackend backend)
|
|
{
|
|
std::vector<std::pair<std::string, std::string>> ret;
|
|
switch (backend)
|
|
{
|
|
#ifndef __ANDROID__
|
|
case AudioBackend::Cubeb:
|
|
ret = GetCubebDriverNames();
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
std::vector<AudioStream::DeviceInfo> AudioStream::GetOutputDevices(AudioBackend backend, std::string_view driver,
|
|
u32 sample_rate)
|
|
{
|
|
std::vector<AudioStream::DeviceInfo> 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> 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;
|
|
}
|
|
}
|