summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorZephyron <zephyron@citron-emu.orgq>2025-02-20 16:54:43 +1000
committerZephyron <zephyron@citron-emu.orgq>2025-02-20 16:54:43 +1000
commit4d50d2ba16d4d08f62a9e2a6626a43d12a36a0e7 (patch)
treea95a23349e32659fc901228387ddd15919d9182d /src
parent0576d40bf0f1044d8702568260282155715ce282 (diff)
Revert "audio: refactor SDL2 sink implementation"
This reverts commit 3aa9c0d1518ceec8e3f9ad93efa84bf90e1f1b21.
Diffstat (limited to 'src')
-rw-r--r--src/audio_core/sink/sdl2_sink.cpp228
-rw-r--r--src/audio_core/sink/sdl2_sink.h18
2 files changed, 132 insertions, 114 deletions
diff --git a/src/audio_core/sink/sdl2_sink.cpp b/src/audio_core/sink/sdl2_sink.cpp
index 8cacd3386..7dd155ff0 100644
--- a/src/audio_core/sink/sdl2_sink.cpp
+++ b/src/audio_core/sink/sdl2_sink.cpp
@@ -1,5 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <span>
@@ -17,9 +16,138 @@ namespace AudioCore::Sink {
/**
* SDL sink stream, responsible for sinking samples to hardware.
*/
-// class SDLSinkStream final : public SinkStream {
-// ...
-// }
+class SDLSinkStream final : public SinkStream {
+public:
+ /**
+ * Create a new sink stream.
+ *
+ * @param device_channels_ - Number of channels supported by the hardware.
+ * @param system_channels_ - Number of channels the audio systems expect.
+ * @param output_device - Name of the output device to use for this stream.
+ * @param input_device - Name of the input device to use for this stream.
+ * @param type_ - Type of this stream.
+ * @param system_ - Core system.
+ * @param event - Event used only for audio renderer, signalled on buffer consume.
+ */
+ SDLSinkStream(u32 device_channels_, u32 system_channels_, const std::string& output_device,
+ const std::string& input_device, StreamType type_, Core::System& system_)
+ : SinkStream{system_, type_} {
+ system_channels = system_channels_;
+ device_channels = device_channels_;
+
+ SDL_AudioSpec spec;
+ spec.freq = TargetSampleRate;
+ spec.channels = static_cast<u8>(device_channels);
+ spec.format = AUDIO_S16SYS;
+ spec.samples = TargetSampleCount * 2;
+ spec.callback = &SDLSinkStream::DataCallback;
+ spec.userdata = this;
+
+ std::string device_name{output_device};
+ bool capture{false};
+ if (type == StreamType::In) {
+ device_name = input_device;
+ capture = true;
+ }
+
+ SDL_AudioSpec obtained;
+ if (device_name.empty()) {
+ device = SDL_OpenAudioDevice(nullptr, capture, &spec, &obtained, false);
+ } else {
+ device = SDL_OpenAudioDevice(device_name.c_str(), capture, &spec, &obtained, false);
+ }
+
+ if (device == 0) {
+ LOG_CRITICAL(Audio_Sink, "Error opening SDL audio device: {}", SDL_GetError());
+ return;
+ }
+
+ LOG_INFO(Service_Audio,
+ "Opening SDL stream {} with: rate {} channels {} (system channels {}) "
+ " samples {}",
+ device, obtained.freq, obtained.channels, system_channels, obtained.samples);
+ }
+
+ /**
+ * Destroy the sink stream.
+ */
+ ~SDLSinkStream() override {
+ LOG_DEBUG(Service_Audio, "Destructing SDL stream {}", name);
+ Finalize();
+ }
+
+ /**
+ * Finalize the sink stream.
+ */
+ void Finalize() override {
+ if (device == 0) {
+ return;
+ }
+
+ Stop();
+ SDL_ClearQueuedAudio(device);
+ SDL_CloseAudioDevice(device);
+ }
+
+ /**
+ * Start the sink stream.
+ *
+ * @param resume - Set to true if this is resuming the stream a previously-active stream.
+ * Default false.
+ */
+ void Start(bool resume = false) override {
+ if (device == 0 || !paused) {
+ return;
+ }
+
+ paused = false;
+ SDL_PauseAudioDevice(device, 0);
+ }
+
+ /**
+ * Stop the sink stream.
+ */
+ void Stop() override {
+ if (device == 0 || paused) {
+ return;
+ }
+ SignalPause();
+ SDL_PauseAudioDevice(device, 1);
+ }
+
+private:
+ /**
+ * Main callback from SDL. Either expects samples from us (audio render/audio out), or will
+ * provide samples to be copied (audio in).
+ *
+ * @param userdata - Custom data pointer passed along, points to a SDLSinkStream.
+ * @param stream - Buffer of samples to be filled or read.
+ * @param len - Length of the stream in bytes.
+ */
+ static void DataCallback(void* userdata, Uint8* stream, int len) {
+ auto* impl = static_cast<SDLSinkStream*>(userdata);
+
+ if (!impl) {
+ return;
+ }
+
+ const std::size_t num_channels = impl->GetDeviceChannels();
+ const std::size_t frame_size = num_channels;
+ const std::size_t num_frames{len / num_channels / sizeof(s16)};
+
+ if (impl->type == StreamType::In) {
+ std::span<const s16> input_buffer{reinterpret_cast<const s16*>(stream),
+ num_frames * frame_size};
+ impl->ProcessAudioIn(input_buffer, num_frames);
+ } else {
+ std::span<s16> output_buffer{reinterpret_cast<s16*>(stream), num_frames * frame_size};
+ impl->ProcessAudioOutAndRender(output_buffer, num_frames);
+ }
+ }
+
+ /// SDL device id of the opened input/output device
+ SDL_AudioDeviceID device{};
+};
SDLSink::SDLSink(std::string_view target_device_name) {
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
@@ -140,96 +268,4 @@ bool IsSDLSuitable() {
#endif
}
-SDLSinkStream::SDLSinkStream(u32 device_channels_, u32 system_channels_, const std::string& output_device,
- const std::string& input_device, StreamType type_, Core::System& system_)
- : SinkStream{system_, type_} {
- system_channels = system_channels_;
- device_channels = device_channels_;
-
- // Add error checking for SDL audio device
- if (SDL_GetNumAudioDevices(0) < 1) {
- LOG_ERROR(Service_Audio, "No audio devices available");
- return;
- }
-
- SDL_AudioSpec want{};
- want.freq = TargetSampleRate;
- want.format = AUDIO_S16LSB;
- want.channels = static_cast<u8>(std::min(device_channels, 2u)); // Limit to stereo
- want.samples = TargetSampleCount * 2; // Match the sample count from logs
- want.callback = nullptr;
-
- SDL_AudioSpec got;
- audio_device_id = SDL_OpenAudioDevice(nullptr, 0, &want, &got,
- SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
-
- if (audio_device_id == 0) {
- LOG_ERROR(Service_Audio, "SDL_OpenAudioDevice failed: {}", SDL_GetError());
- return;
- }
-
- // Verify we got the requested format
- if (got.format != want.format || got.channels != want.channels) {
- LOG_WARNING(Service_Audio,
- "SDL audio format mismatch - wanted: {} ch, got: {} ch",
- want.channels, got.channels);
- }
-
- running = true;
- SDL_PauseAudioDevice(audio_device_id, 0);
-}
-
-SDLSinkStream::~SDLSinkStream() {
- LOG_DEBUG(Service_Audio, "Destructing SDL stream {}", name);
- Finalize();
-}
-
-void SDLSinkStream::Finalize() {
- if (audio_device_id == 0) {
- return;
- }
-
- Stop();
- SDL_ClearQueuedAudio(audio_device_id);
- SDL_CloseAudioDevice(audio_device_id);
-}
-
-void SDLSinkStream::Start(bool resume) {
- if (audio_device_id == 0 || !paused) {
- return;
- }
-
- paused = false;
- SDL_PauseAudioDevice(audio_device_id, 0);
-}
-
-void SDLSinkStream::Stop() {
- if (audio_device_id == 0 || paused) {
- return;
- }
- SignalPause();
- SDL_PauseAudioDevice(audio_device_id, 1);
-}
-
-void SDLSinkStream::DataCallback(void* userdata, Uint8* stream, int len) {
- auto* impl = static_cast<SDLSinkStream*>(userdata);
-
- if (!impl) {
- return;
- }
-
- const std::size_t num_channels = impl->GetDeviceChannels();
- const std::size_t frame_size = num_channels;
- const std::size_t num_frames{len / num_channels / sizeof(s16)};
-
- if (impl->type == StreamType::In) {
- std::span<const s16> input_buffer{reinterpret_cast<const s16*>(stream),
- num_frames * frame_size};
- impl->ProcessAudioIn(input_buffer, num_frames);
- } else {
- std::span<s16> output_buffer{reinterpret_cast<s16*>(stream), num_frames * frame_size};
- impl->ProcessAudioOutAndRender(output_buffer, num_frames);
- }
-}
-
} // namespace AudioCore::Sink
diff --git a/src/audio_core/sink/sdl2_sink.h b/src/audio_core/sink/sdl2_sink.h
index fef145273..9211d2e97 100644
--- a/src/audio_core/sink/sdl2_sink.h
+++ b/src/audio_core/sink/sdl2_sink.h
@@ -5,7 +5,6 @@
#include <string>
#include <vector>
-#include <SDL.h>
#include "audio_core/sink/sink.h"
@@ -96,21 +95,4 @@ std::vector<std::string> ListSDLSinkDevices(bool capture);
*/
bool IsSDLSuitable();
-class SDLSinkStream final : public SinkStream {
-public:
- SDLSinkStream(u32 sample_rate, u32 num_channels, const std::string& output_device,
- const std::string& input_device, StreamType type, Core::System& system);
- ~SDLSinkStream();
-
- void Start(bool resume) override;
- void Stop() override;
- void Finalize();
-
-private:
- void DataCallback(void* userdata, Uint8* stream, int len);
-
- bool running{false};
- SDL_AudioDeviceID audio_device_id{};
-};
-
} // namespace AudioCore::Sink