summaryrefslogtreecommitdiff
path: root/src/audio_core/sdl2_sink.cpp
diff options
context:
space:
mode:
authorGravatar Kelebek12022-07-16 23:48:45 +0100
committerGravatar Kelebek12022-07-22 01:11:32 +0100
commit458da8a94877677f086f06cdeecf959ec4283a33 (patch)
tree583166d77602ad90a0d552f37de8729ad80fd6c1 /src/audio_core/sdl2_sink.cpp
parentMerge pull request #8598 from Link4565/recv-dontwait (diff)
downloadyuzu-458da8a94877677f086f06cdeecf959ec4283a33.tar.gz
yuzu-458da8a94877677f086f06cdeecf959ec4283a33.tar.xz
yuzu-458da8a94877677f086f06cdeecf959ec4283a33.zip
Project Andio
Diffstat (limited to 'src/audio_core/sdl2_sink.cpp')
-rw-r--r--src/audio_core/sdl2_sink.cpp160
1 files changed, 0 insertions, 160 deletions
diff --git a/src/audio_core/sdl2_sink.cpp b/src/audio_core/sdl2_sink.cpp
deleted file mode 100644
index a10ba4044..000000000
--- a/src/audio_core/sdl2_sink.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <algorithm>
5#include <atomic>
6#include <cstring>
7#include "audio_core/sdl2_sink.h"
8#include "audio_core/stream.h"
9#include "common/assert.h"
10#include "common/logging/log.h"
11//#include "common/settings.h"
12
13// Ignore -Wimplicit-fallthrough due to https://github.com/libsdl-org/SDL/issues/4307
14#ifdef __clang__
15#pragma clang diagnostic push
16#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
17#endif
18#include <SDL.h>
19#ifdef __clang__
20#pragma clang diagnostic pop
21#endif
22
23namespace AudioCore {
24
25class SDLSinkStream final : public SinkStream {
26public:
27 SDLSinkStream(u32 sample_rate, u32 num_channels_, const std::string& output_device)
28 : num_channels{std::min(num_channels_, 6u)} {
29
30 SDL_AudioSpec spec;
31 spec.freq = sample_rate;
32 spec.channels = static_cast<u8>(num_channels);
33 spec.format = AUDIO_S16SYS;
34 spec.samples = 4096;
35 spec.callback = nullptr;
36
37 SDL_AudioSpec obtained;
38 if (output_device.empty()) {
39 dev = SDL_OpenAudioDevice(nullptr, 0, &spec, &obtained, 0);
40 } else {
41 dev = SDL_OpenAudioDevice(output_device.c_str(), 0, &spec, &obtained, 0);
42 }
43
44 if (dev == 0) {
45 LOG_CRITICAL(Audio_Sink, "Error opening sdl audio device: {}", SDL_GetError());
46 return;
47 }
48
49 SDL_PauseAudioDevice(dev, 0);
50 }
51
52 ~SDLSinkStream() override {
53 if (dev == 0) {
54 return;
55 }
56
57 SDL_CloseAudioDevice(dev);
58 }
59
60 void EnqueueSamples(u32 source_num_channels, const std::vector<s16>& samples) override {
61 if (source_num_channels > num_channels) {
62 // Downsample 6 channels to 2
63 ASSERT_MSG(source_num_channels == 6, "Channel count must be 6");
64
65 std::vector<s16> buf;
66 buf.reserve(samples.size() * num_channels / source_num_channels);
67 for (std::size_t i = 0; i < samples.size(); i += source_num_channels) {
68 // Downmixing implementation taken from the ATSC standard
69 const s16 left{samples[i + 0]};
70 const s16 right{samples[i + 1]};
71 const s16 center{samples[i + 2]};
72 const s16 surround_left{samples[i + 4]};
73 const s16 surround_right{samples[i + 5]};
74 // Not used in the ATSC reference implementation
75 [[maybe_unused]] const s16 low_frequency_effects{samples[i + 3]};
76
77 constexpr s32 clev{707}; // center mixing level coefficient
78 constexpr s32 slev{707}; // surround mixing level coefficient
79
80 buf.push_back(static_cast<s16>(left + (clev * center / 1000) +
81 (slev * surround_left / 1000)));
82 buf.push_back(static_cast<s16>(right + (clev * center / 1000) +
83 (slev * surround_right / 1000)));
84 }
85 int ret = SDL_QueueAudio(dev, static_cast<const void*>(buf.data()),
86 static_cast<u32>(buf.size() * sizeof(s16)));
87 if (ret < 0)
88 LOG_WARNING(Audio_Sink, "Could not queue audio buffer: {}", SDL_GetError());
89 return;
90 }
91
92 int ret = SDL_QueueAudio(dev, static_cast<const void*>(samples.data()),
93 static_cast<u32>(samples.size() * sizeof(s16)));
94 if (ret < 0)
95 LOG_WARNING(Audio_Sink, "Could not queue audio buffer: {}", SDL_GetError());
96 }
97
98 std::size_t SamplesInQueue(u32 channel_count) const override {
99 if (dev == 0)
100 return 0;
101
102 return SDL_GetQueuedAudioSize(dev) / (channel_count * sizeof(s16));
103 }
104
105 void Flush() override {
106 should_flush = true;
107 }
108
109 u32 GetNumChannels() const {
110 return num_channels;
111 }
112
113private:
114 SDL_AudioDeviceID dev = 0;
115 u32 num_channels{};
116 std::atomic<bool> should_flush{};
117};
118
119SDLSink::SDLSink(std::string_view target_device_name) {
120 if (!SDL_WasInit(SDL_INIT_AUDIO)) {
121 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
122 LOG_CRITICAL(Audio_Sink, "SDL_InitSubSystem audio failed: {}", SDL_GetError());
123 return;
124 }
125 }
126
127 if (target_device_name != auto_device_name && !target_device_name.empty()) {
128 output_device = target_device_name;
129 } else {
130 output_device.clear();
131 }
132}
133
134SDLSink::~SDLSink() = default;
135
136SinkStream& SDLSink::AcquireSinkStream(u32 sample_rate, u32 num_channels, const std::string&) {
137 sink_streams.push_back(
138 std::make_unique<SDLSinkStream>(sample_rate, num_channels, output_device));
139 return *sink_streams.back();
140}
141
142std::vector<std::string> ListSDLSinkDevices() {
143 std::vector<std::string> device_list;
144
145 if (!SDL_WasInit(SDL_INIT_AUDIO)) {
146 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
147 LOG_CRITICAL(Audio_Sink, "SDL_InitSubSystem audio failed: {}", SDL_GetError());
148 return {};
149 }
150 }
151
152 const int device_count = SDL_GetNumAudioDevices(0);
153 for (int i = 0; i < device_count; ++i) {
154 device_list.emplace_back(SDL_GetAudioDeviceName(i, 0));
155 }
156
157 return device_list;
158}
159
160} // namespace AudioCore