2019-10-10 16:20:10 +00:00
|
|
|
#include "sdl_audio_stream.h"
|
2020-01-10 03:31:12 +00:00
|
|
|
#include "common/assert.h"
|
|
|
|
#include "common/log.h"
|
2020-06-06 04:40:20 +00:00
|
|
|
#include "sdl_initializer.h"
|
2019-10-10 16:20:10 +00:00
|
|
|
#include <SDL.h>
|
|
|
|
Log_SetChannel(SDLAudioStream);
|
|
|
|
|
|
|
|
SDLAudioStream::SDLAudioStream() = default;
|
|
|
|
|
|
|
|
SDLAudioStream::~SDLAudioStream()
|
|
|
|
{
|
2020-06-06 04:40:20 +00:00
|
|
|
if (IsOpen())
|
2019-10-10 16:20:10 +00:00
|
|
|
SDLAudioStream::CloseDevice();
|
|
|
|
}
|
|
|
|
|
2020-02-15 15:14:35 +00:00
|
|
|
std::unique_ptr<SDLAudioStream> SDLAudioStream::Create()
|
|
|
|
{
|
|
|
|
return std::make_unique<SDLAudioStream>();
|
|
|
|
}
|
|
|
|
|
2019-10-10 16:20:10 +00:00
|
|
|
bool SDLAudioStream::OpenDevice()
|
|
|
|
{
|
2020-06-06 04:40:20 +00:00
|
|
|
DebugAssert(!IsOpen());
|
2019-10-10 16:20:10 +00:00
|
|
|
|
2020-02-15 15:15:05 +00:00
|
|
|
FrontendCommon::EnsureSDLInitialized();
|
|
|
|
|
|
|
|
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
|
|
|
|
{
|
|
|
|
Log_ErrorPrintf("SDL_InitSubSystem(SDL_INIT_AUDIO) failed");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-10-10 16:20:10 +00:00
|
|
|
SDL_AudioSpec spec = {};
|
|
|
|
spec.freq = m_output_sample_rate;
|
2019-10-26 15:58:28 +00:00
|
|
|
spec.channels = static_cast<Uint8>(m_channels);
|
2019-10-10 16:20:10 +00:00
|
|
|
spec.format = AUDIO_S16;
|
2019-10-26 15:58:28 +00:00
|
|
|
spec.samples = static_cast<Uint16>(m_buffer_size);
|
2019-10-10 16:20:10 +00:00
|
|
|
spec.callback = AudioCallback;
|
|
|
|
spec.userdata = static_cast<void*>(this);
|
|
|
|
|
2020-06-06 04:40:20 +00:00
|
|
|
SDL_AudioSpec obtained_spec = {};
|
2020-06-06 15:38:38 +00:00
|
|
|
|
|
|
|
#ifdef SDL_AUDIO_ALLOW_SAMPLES_CHANGE
|
|
|
|
const u32 allowed_change_flags = SDL_AUDIO_ALLOW_SAMPLES_CHANGE;
|
|
|
|
#else
|
|
|
|
const u32 allowed_change_flags = 0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
m_device_id = SDL_OpenAudioDevice(nullptr, 0, &spec, &obtained_spec, allowed_change_flags);
|
2020-06-06 04:40:20 +00:00
|
|
|
if (m_device_id == 0)
|
2019-10-10 16:20:10 +00:00
|
|
|
{
|
2020-06-06 04:40:20 +00:00
|
|
|
Log_ErrorPrintf("SDL_OpenAudioDevice() failed: %s", SDL_GetError());
|
2020-02-15 15:15:05 +00:00
|
|
|
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
2019-10-10 16:20:10 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-06-06 04:40:20 +00:00
|
|
|
if (obtained_spec.samples > spec.samples)
|
|
|
|
{
|
|
|
|
Log_WarningPrintf("Requested buffer size %u, got buffer size %u. Adjusting to compensate.", spec.samples,
|
|
|
|
obtained_spec.samples);
|
|
|
|
|
|
|
|
if (!SetBufferSize(obtained_spec.samples))
|
|
|
|
{
|
|
|
|
Log_ErrorPrintf("Failed to set new buffer size of %u", obtained_spec.samples);
|
|
|
|
CloseDevice();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-10 16:20:10 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDLAudioStream::PauseDevice(bool paused)
|
|
|
|
{
|
2020-06-06 04:40:20 +00:00
|
|
|
SDL_PauseAudioDevice(m_device_id, paused ? 1 : 0);
|
2019-10-10 16:20:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SDLAudioStream::CloseDevice()
|
|
|
|
{
|
2020-06-06 04:40:20 +00:00
|
|
|
SDL_CloseAudioDevice(m_device_id);
|
2020-02-15 15:15:05 +00:00
|
|
|
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
2020-06-06 04:40:20 +00:00
|
|
|
m_device_id = 0;
|
2019-10-10 16:20:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SDLAudioStream::AudioCallback(void* userdata, uint8_t* stream, int len)
|
|
|
|
{
|
|
|
|
SDLAudioStream* const this_ptr = static_cast<SDLAudioStream*>(userdata);
|
2020-06-06 04:40:20 +00:00
|
|
|
const u32 num_frames = len / sizeof(SampleType) / this_ptr->m_channels;
|
|
|
|
|
2020-12-12 01:50:48 +00:00
|
|
|
this_ptr->ReadFrames(reinterpret_cast<SampleType*>(stream), num_frames, true);
|
2019-10-10 16:20:10 +00:00
|
|
|
}
|
2019-12-23 07:02:11 +00:00
|
|
|
|
2020-06-06 04:40:20 +00:00
|
|
|
void SDLAudioStream::FramesAvailable() {}
|