OpenAL: destroy context when not in use
This prevents the CoreAudio thread from spinning when paused on macOS
This commit is contained in:
parent
5a3b7301c6
commit
16d57dac79
1 changed files with 30 additions and 12 deletions
|
@ -104,6 +104,9 @@ class OpenALPlayer final : public AudioPlayer, wxTimer {
|
||||||
/// wxTimer override to periodically fill available buffers
|
/// wxTimer override to periodically fill available buffers
|
||||||
void Notify() override;
|
void Notify() override;
|
||||||
|
|
||||||
|
void InitContext();
|
||||||
|
void TeardownContext();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OpenALPlayer(agi::AudioProvider *provider);
|
OpenALPlayer(agi::AudioProvider *provider);
|
||||||
~OpenALPlayer();
|
~OpenALPlayer();
|
||||||
|
@ -124,11 +127,24 @@ OpenALPlayer::OpenALPlayer(agi::AudioProvider *provider)
|
||||||
, samplerate(provider->GetSampleRate())
|
, samplerate(provider->GetSampleRate())
|
||||||
, bpf(provider->GetChannels() * provider->GetBytesPerSample())
|
, bpf(provider->GetChannels() * provider->GetBytesPerSample())
|
||||||
{
|
{
|
||||||
try {
|
|
||||||
// Open device
|
|
||||||
device = alcOpenDevice(nullptr);
|
device = alcOpenDevice(nullptr);
|
||||||
if (!device) throw AudioPlayerOpenError("Failed opening default OpenAL device");
|
if (!device) throw AudioPlayerOpenError("Failed opening default OpenAL device");
|
||||||
|
|
||||||
|
// Determine buffer length
|
||||||
|
decode_buffer.resize(samplerate * bpf / num_buffers / 2); // buffers for half a second of audio
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenALPlayer::~OpenALPlayer()
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
alcCloseDevice(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenALPlayer::InitContext()
|
||||||
|
{
|
||||||
|
if (context) return;
|
||||||
|
|
||||||
|
try {
|
||||||
// Create context
|
// Create context
|
||||||
context = alcCreateContext(device, nullptr);
|
context = alcCreateContext(device, nullptr);
|
||||||
if (!context) throw AudioPlayerOpenError("Failed creating OpenAL context");
|
if (!context) throw AudioPlayerOpenError("Failed creating OpenAL context");
|
||||||
|
@ -151,27 +167,25 @@ OpenALPlayer::OpenALPlayer(agi::AudioProvider *provider)
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
alcDestroyContext(context);
|
alcDestroyContext(context);
|
||||||
alcCloseDevice(device);
|
context = nullptr;
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine buffer length
|
|
||||||
decode_buffer.resize(samplerate * bpf / num_buffers / 2); // buffers for half a second of audio
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenALPlayer::~OpenALPlayer()
|
void OpenALPlayer::TeardownContext()
|
||||||
{
|
{
|
||||||
Stop();
|
if (!context) return;
|
||||||
|
|
||||||
alcMakeContextCurrent(context);
|
alcMakeContextCurrent(context);
|
||||||
alDeleteSources(1, &source);
|
alDeleteSources(1, &source);
|
||||||
alDeleteBuffers(num_buffers, buffers);
|
alDeleteBuffers(num_buffers, buffers);
|
||||||
|
alcMakeContextCurrent(nullptr);
|
||||||
alcDestroyContext(context);
|
alcDestroyContext(context);
|
||||||
alcCloseDevice(device);
|
context = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenALPlayer::Play(int64_t start, int64_t count)
|
void OpenALPlayer::Play(int64_t start, int64_t count)
|
||||||
{
|
{
|
||||||
|
InitContext();
|
||||||
alcMakeContextCurrent(context);
|
alcMakeContextCurrent(context);
|
||||||
if (playing) {
|
if (playing) {
|
||||||
// Quick reset
|
// Quick reset
|
||||||
|
@ -201,6 +215,7 @@ void OpenALPlayer::Play(int64_t start, int64_t count)
|
||||||
|
|
||||||
void OpenALPlayer::Stop()
|
void OpenALPlayer::Stop()
|
||||||
{
|
{
|
||||||
|
TeardownContext();
|
||||||
if (!playing) return;
|
if (!playing) return;
|
||||||
|
|
||||||
// Reset data
|
// Reset data
|
||||||
|
@ -214,10 +229,12 @@ void OpenALPlayer::Stop()
|
||||||
alcMakeContextCurrent(context);
|
alcMakeContextCurrent(context);
|
||||||
alSourceStop(source);
|
alSourceStop(source);
|
||||||
alSourcei(source, AL_BUFFER, 0);
|
alSourcei(source, AL_BUFFER, 0);
|
||||||
|
alcMakeContextCurrent(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenALPlayer::FillBuffers(ALsizei count)
|
void OpenALPlayer::FillBuffers(ALsizei count)
|
||||||
{
|
{
|
||||||
|
InitContext();
|
||||||
// Do the actual filling/queueing
|
// Do the actual filling/queueing
|
||||||
for (count = mid(1, count, buffers_free); count > 0; --count) {
|
for (count = mid(1, count, buffers_free); count > 0; --count) {
|
||||||
ALsizei fill_len = mid<ALsizei>(0, decode_buffer.size() / bpf, end_frame - cur_frame);
|
ALsizei fill_len = mid<ALsizei>(0, decode_buffer.size() / bpf, end_frame - cur_frame);
|
||||||
|
@ -240,6 +257,7 @@ void OpenALPlayer::FillBuffers(ALsizei count)
|
||||||
|
|
||||||
void OpenALPlayer::Notify()
|
void OpenALPlayer::Notify()
|
||||||
{
|
{
|
||||||
|
InitContext();
|
||||||
alcMakeContextCurrent(context);
|
alcMakeContextCurrent(context);
|
||||||
ALsizei newplayed;
|
ALsizei newplayed;
|
||||||
alGetSourcei(source, AL_BUFFERS_PROCESSED, &newplayed);
|
alGetSourcei(source, AL_BUFFERS_PROCESSED, &newplayed);
|
||||||
|
|
Loading…
Reference in a new issue