diff options
Diffstat (limited to 'src/audio_core/sdl2_sink.cpp')
| -rw-r--r-- | src/audio_core/sdl2_sink.cpp | 147 |
1 files changed, 0 insertions, 147 deletions
diff --git a/src/audio_core/sdl2_sink.cpp b/src/audio_core/sdl2_sink.cpp deleted file mode 100644 index 933c5f16d..000000000 --- a/src/audio_core/sdl2_sink.cpp +++ /dev/null | |||
| @@ -1,147 +0,0 @@ | |||
| 1 | // Copyright 2016 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <list> | ||
| 6 | #include <numeric> | ||
| 7 | #include <SDL.h> | ||
| 8 | #include "audio_core/audio_core.h" | ||
| 9 | #include "audio_core/sdl2_sink.h" | ||
| 10 | #include "common/assert.h" | ||
| 11 | #include "common/logging/log.h" | ||
| 12 | #include "core/settings.h" | ||
| 13 | |||
| 14 | namespace AudioCore { | ||
| 15 | |||
| 16 | struct SDL2Sink::Impl { | ||
| 17 | unsigned int sample_rate = 0; | ||
| 18 | |||
| 19 | SDL_AudioDeviceID audio_device_id = 0; | ||
| 20 | |||
| 21 | std::list<std::vector<s16>> queue; | ||
| 22 | |||
| 23 | static void Callback(void* impl_, u8* buffer, int buffer_size_in_bytes); | ||
| 24 | }; | ||
| 25 | |||
| 26 | SDL2Sink::SDL2Sink() : impl(std::make_unique<Impl>()) { | ||
| 27 | if (SDL_Init(SDL_INIT_AUDIO) < 0) { | ||
| 28 | LOG_CRITICAL(Audio_Sink, "SDL_Init(SDL_INIT_AUDIO) failed with: %s", SDL_GetError()); | ||
| 29 | impl->audio_device_id = 0; | ||
| 30 | return; | ||
| 31 | } | ||
| 32 | |||
| 33 | SDL_AudioSpec desired_audiospec; | ||
| 34 | SDL_zero(desired_audiospec); | ||
| 35 | desired_audiospec.format = AUDIO_S16; | ||
| 36 | desired_audiospec.channels = 2; | ||
| 37 | desired_audiospec.freq = native_sample_rate; | ||
| 38 | desired_audiospec.samples = 512; | ||
| 39 | desired_audiospec.userdata = impl.get(); | ||
| 40 | desired_audiospec.callback = &Impl::Callback; | ||
| 41 | |||
| 42 | SDL_AudioSpec obtained_audiospec; | ||
| 43 | SDL_zero(obtained_audiospec); | ||
| 44 | |||
| 45 | int device_count = SDL_GetNumAudioDevices(0); | ||
| 46 | device_list.clear(); | ||
| 47 | for (int i = 0; i < device_count; ++i) { | ||
| 48 | device_list.push_back(SDL_GetAudioDeviceName(i, 0)); | ||
| 49 | } | ||
| 50 | |||
| 51 | const char* device = nullptr; | ||
| 52 | |||
| 53 | if (device_count >= 1 && Settings::values.audio_device_id != "auto" && | ||
| 54 | !Settings::values.audio_device_id.empty()) { | ||
| 55 | device = Settings::values.audio_device_id.c_str(); | ||
| 56 | } | ||
| 57 | |||
| 58 | impl->audio_device_id = SDL_OpenAudioDevice(device, false, &desired_audiospec, | ||
| 59 | &obtained_audiospec, SDL_AUDIO_ALLOW_ANY_CHANGE); | ||
| 60 | if (impl->audio_device_id <= 0) { | ||
| 61 | LOG_CRITICAL(Audio_Sink, "SDL_OpenAudioDevice failed with code %d for device \"%s\"", | ||
| 62 | impl->audio_device_id, Settings::values.audio_device_id.c_str()); | ||
| 63 | return; | ||
| 64 | } | ||
| 65 | |||
| 66 | impl->sample_rate = obtained_audiospec.freq; | ||
| 67 | |||
| 68 | // SDL2 audio devices start out paused, unpause it: | ||
| 69 | SDL_PauseAudioDevice(impl->audio_device_id, 0); | ||
| 70 | } | ||
| 71 | |||
| 72 | SDL2Sink::~SDL2Sink() { | ||
| 73 | if (impl->audio_device_id <= 0) | ||
| 74 | return; | ||
| 75 | |||
| 76 | SDL_CloseAudioDevice(impl->audio_device_id); | ||
| 77 | } | ||
| 78 | |||
| 79 | unsigned int SDL2Sink::GetNativeSampleRate() const { | ||
| 80 | if (impl->audio_device_id <= 0) | ||
| 81 | return native_sample_rate; | ||
| 82 | |||
| 83 | return impl->sample_rate; | ||
| 84 | } | ||
| 85 | |||
| 86 | std::vector<std::string> SDL2Sink::GetDeviceList() const { | ||
| 87 | return device_list; | ||
| 88 | } | ||
| 89 | |||
| 90 | void SDL2Sink::EnqueueSamples(const s16* samples, size_t sample_count) { | ||
| 91 | if (impl->audio_device_id <= 0) | ||
| 92 | return; | ||
| 93 | |||
| 94 | SDL_LockAudioDevice(impl->audio_device_id); | ||
| 95 | impl->queue.emplace_back(samples, samples + sample_count * 2); | ||
| 96 | SDL_UnlockAudioDevice(impl->audio_device_id); | ||
| 97 | } | ||
| 98 | |||
| 99 | size_t SDL2Sink::SamplesInQueue() const { | ||
| 100 | if (impl->audio_device_id <= 0) | ||
| 101 | return 0; | ||
| 102 | |||
| 103 | SDL_LockAudioDevice(impl->audio_device_id); | ||
| 104 | |||
| 105 | size_t total_size = std::accumulate(impl->queue.begin(), impl->queue.end(), | ||
| 106 | static_cast<size_t>(0), [](size_t sum, const auto& buffer) { | ||
| 107 | // Division by two because each stereo sample is made of | ||
| 108 | // two s16. | ||
| 109 | return sum + buffer.size() / 2; | ||
| 110 | }); | ||
| 111 | |||
| 112 | SDL_UnlockAudioDevice(impl->audio_device_id); | ||
| 113 | |||
| 114 | return total_size; | ||
| 115 | } | ||
| 116 | |||
| 117 | void SDL2Sink::SetDevice(int device_id) { | ||
| 118 | this->device_id = device_id; | ||
| 119 | } | ||
| 120 | |||
| 121 | void SDL2Sink::Impl::Callback(void* impl_, u8* buffer, int buffer_size_in_bytes) { | ||
| 122 | Impl* impl = reinterpret_cast<Impl*>(impl_); | ||
| 123 | |||
| 124 | size_t remaining_size = static_cast<size_t>(buffer_size_in_bytes) / | ||
| 125 | sizeof(s16); // Keep track of size in 16-bit increments. | ||
| 126 | |||
| 127 | while (remaining_size > 0 && !impl->queue.empty()) { | ||
| 128 | if (impl->queue.front().size() <= remaining_size) { | ||
| 129 | memcpy(buffer, impl->queue.front().data(), impl->queue.front().size() * sizeof(s16)); | ||
| 130 | buffer += impl->queue.front().size() * sizeof(s16); | ||
| 131 | remaining_size -= impl->queue.front().size(); | ||
| 132 | impl->queue.pop_front(); | ||
| 133 | } else { | ||
| 134 | memcpy(buffer, impl->queue.front().data(), remaining_size * sizeof(s16)); | ||
| 135 | buffer += remaining_size * sizeof(s16); | ||
| 136 | impl->queue.front().erase(impl->queue.front().begin(), | ||
| 137 | impl->queue.front().begin() + remaining_size); | ||
| 138 | remaining_size = 0; | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | if (remaining_size > 0) { | ||
| 143 | memset(buffer, 0, remaining_size * sizeof(s16)); | ||
| 144 | } | ||
| 145 | } | ||
| 146 | |||
| 147 | } // namespace AudioCore | ||