24 LOG_WARN(
"AudioBackend",
"Already initialized, shutting down first");
30 SDL_AudioSpec want, have;
31 SDL_memset(&want, 0,
sizeof(want));
37 want.callback =
nullptr;
39 device_id_ = SDL_OpenAudioDevice(
nullptr, 0, &want, &have, 0);
42 LOG_ERROR(
"AudioBackend",
"Failed to open SDL audio device: %s", SDL_GetError());
51 if (have.freq != want.freq || have.channels != want.channels) {
53 "Audio spec mismatch - wanted %dHz %dch, got %dHz %dch",
54 want.freq, want.channels, have.freq, have.channels);
60 LOG_INFO(
"AudioBackend",
"SDL2 audio initialized: %dHz, %d channels, %d samples buffer",
61 have.freq, have.channels, have.samples);
96 LOG_INFO(
"AudioBackend",
"SDL2 audio shut down");
129 int result = SDL_QueueAudio(
device_id_, samples, num_samples *
sizeof(int16_t));
131 LOG_ERROR(
"AudioBackend",
"SDL_QueueAudio failed: %s", SDL_GetError());
139 thread_local std::vector<int16_t> scaled_samples;
142 if (scaled_samples.size() <
static_cast<size_t>(num_samples)) {
143 scaled_samples.resize(num_samples);
147 for (
int i = 0; i < num_samples; ++i) {
148 int32_t scaled =
static_cast<int32_t
>(samples[i] *
volume_);
150 if (scaled > 32767) scaled = 32767;
151 else if (scaled < -32768) scaled = -32768;
152 scaled_samples[i] =
static_cast<int16_t
>(scaled);
155 int result = SDL_QueueAudio(
device_id_, scaled_samples.data(),
156 num_samples *
sizeof(int16_t));
158 LOG_ERROR(
"AudioBackend",
"SDL_QueueAudio failed: %s", SDL_GetError());
169 std::vector<int16_t> int_samples(num_samples);
170 for (
int i = 0; i < num_samples; ++i) {
171 float scaled = std::clamp(samples[i] *
volume_, -1.0f, 1.0f);
172 int_samples[i] =
static_cast<int16_t
>(scaled * 32767.0f);
179 int frames_per_channel,
int channels,
198 frames_per_channel * channels *
static_cast<int>(
sizeof(int16_t));
200 if (SDL_AudioStreamPut(
audio_stream_, samples, bytes_in) < 0) {
201 LOG_ERROR(
"AudioBackend",
"SDL_AudioStreamPut failed: %s", SDL_GetError());
205 const int available_bytes = SDL_AudioStreamAvailable(
audio_stream_);
206 if (available_bytes < 0) {
207 LOG_ERROR(
"AudioBackend",
"SDL_AudioStreamAvailable failed: %s", SDL_GetError());
211 if (available_bytes == 0) {
215 const int available_samples = available_bytes /
static_cast<int>(
sizeof(int16_t));
216 if (
static_cast<int>(
stream_buffer_.size()) < available_samples) {
221 LOG_ERROR(
"AudioBackend",
"SDL_AudioStreamGet failed: %s", SDL_GetError());
272 const bool needs_recreate =
276 if (!needs_recreate) {
286 audio_stream_ = SDL_NewAudioStream(AUDIO_S16, channels, native_rate,
290 LOG_ERROR(
"AudioBackend",
"SDL_NewAudioStream failed: %s", SDL_GetError());
303 volume_ = std::clamp(volume, 0.0f, 1.0f);
317 return std::make_unique<SDL2AudioBackend>();
321 LOG_WARN(
"AudioBackend",
"NULL backend not yet implemented, using SDL2");
322 return std::make_unique<SDL2AudioBackend>();
325 LOG_ERROR(
"AudioBackend",
"Unknown backend type, using SDL2");
326 return std::make_unique<SDL2AudioBackend>();
static std::unique_ptr< IAudioBackend > Create(BackendType type)
AudioConfig GetConfig() const override
SDL_AudioFormat device_format_
void SetVolume(float volume) override
bool Initialize(const AudioConfig &config) override
~SDL2AudioBackend() override
bool IsInitialized() const override
std::vector< int16_t > stream_buffer_
bool audio_stream_enabled_
SDL_AudioStream * audio_stream_
AudioStatus GetStatus() const override
float GetVolume() const override
bool QueueSamplesNative(const int16_t *samples, int frames_per_channel, int channels, int native_rate) override
bool QueueSamples(const int16_t *samples, int num_samples) override
void SetAudioStreamResampling(bool enable, int native_rate, int channels) override
#define LOG_ERROR(category, format,...)
#define LOG_WARN(category, format,...)
#define LOG_INFO(category, format,...)
Main namespace for the application.