2 #include <ossia/detail/config.hpp>
4 #if defined(OSSIA_ENABLE_SDL)
5 #if __has_include(<SDL2/SDL_audio.h>)
6 #include <SDL2/SDL_config.h>
7 #if !defined(SDL_AUDIO_DISABLED)
8 #include <ossia/audio/audio_engine.hpp>
9 #include <ossia/detail/thread.hpp>
12 #include <SDL2/SDL_audio.h>
14 #define OSSIA_AUDIO_SDL 1
18 class sdl_protocol final :
public audio_engine
20 static constexpr
int inputs = 0;
21 static constexpr
int outputs = 2;
24 sdl_protocol(
int rate,
int bs)
26 SDL_Init(SDL_INIT_AUDIO);
27 m_desired.freq = rate;
28 m_desired.format = AUDIO_F32SYS;
29 m_desired.channels = outputs;
30 m_desired.samples = bs;
31 m_desired.callback = SDLCallback;
32 m_desired.userdata =
this;
34 m_deviceId = SDL_OpenAudioDevice(
nullptr, 0, &m_desired, &m_obtained, 0);
38 using namespace std::literals;
39 throw std::runtime_error(
"SDL: Couldn't open audio: "s + SDL_GetError());
42 this->effective_sample_rate = m_obtained.freq;
43 this->effective_buffer_size = m_obtained.samples;
44 this->effective_inputs = 0;
45 this->effective_outputs = m_obtained.channels;
47 SDL_PauseAudioDevice(m_deviceId, 0);
50 ~sdl_protocol()
override
53 SDL_CloseAudioDevice(m_deviceId);
57 bool running()
const override
59 return SDL_GetAudioDeviceStatus(m_deviceId) == SDL_AUDIO_PLAYING;
63 static void SDLCallback(
void* userData, Uint8* data,
int bytes)
65 static const thread_local
auto _ = [] {
66 ossia::set_thread_name(
"ossia audio 0");
67 ossia::set_thread_pinned(thread_type::Audio, 0);
71 auto&
self = *
static_cast<sdl_protocol*
>(userData);
74 auto audio_out =
reinterpret_cast<float*
>(data);
75 const int out_chan =
self.m_obtained.channels;
76 const int frames =
self.m_obtained.samples;
79 assert(frames * out_chan *
sizeof(
float) == bytes);
81 if(
self.stop_processing)
84 memset(data, 0, bytes);
89 auto float_data = (
float*)alloca(
sizeof(
float) * frames * out_chan);
90 memset(float_data, 0,
sizeof(
sizeof(
float) * frames * out_chan));
92 auto float_output = (
float**)alloca(
sizeof(
float*) * out_chan);
94 for(
int c = 0; c < out_chan; c++)
96 float_output[c] = float_data + c * frames;
102 ossia::audio_tick_state ts{
nullptr, float_output, 0,
103 out_chan, (uint64_t)frames, 0};
106 for(
int j = 0; j < frames; j++)
107 for(
int c = 0; c < out_chan; c++)
108 *audio_out++ = float_output[c][j];
114 SDL_AudioDeviceID m_deviceId{};
115 SDL_AudioSpec m_desired, m_obtained;