diff options
author | Jan Niklas Hasse <[email protected]> | 2018-03-08 09:50:16 +0100 |
---|---|---|
committer | Jan Niklas Hasse <[email protected]> | 2018-03-08 09:51:44 +0100 |
commit | 767807cd2273eb9e760b25d792820b1c8f1946e1 (patch) | |
tree | d44dd3ba5b9ccf6cfbbb9bd5dfdc591a0c4673ef | |
parent | 86319127e3e377312f815d55693f7b46569cde62 (diff) |
SDL2 backend: Use callback instead of a timing loop
The system clock and audio clock aren't necessarily synchronized.
-rw-r--r-- | Alc/backends/sdl2.c | 94 |
1 files changed, 11 insertions, 83 deletions
diff --git a/Alc/backends/sdl2.c b/Alc/backends/sdl2.c index 4b2d3acd..c191a528 100644 --- a/Alc/backends/sdl2.c +++ b/Alc/backends/sdl2.c @@ -35,15 +35,10 @@ typedef struct ALCsdl2Backend { DERIVE_FROM_TYPE(ALCbackend); SDL_AudioDeviceID deviceID; - ALvoid *mBuffer; - ALuint mSize; ALCboolean quit; - ATOMIC(int) killNow; althrd_t thread; } ALCsdl2Backend; -static int ALCsdl2Backend_mixerProc(void *ptr); - static void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device); static DECLARE_FORWARD(ALCsdl2Backend, ALCbackend, void, Destruct) static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name); @@ -64,8 +59,6 @@ static void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device) ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); SET_VTABLE2(ALCsdl2Backend, ALCbackend, self); - self->mBuffer = NULL; - self->mSize = 0; self->quit = ALC_FALSE; if(SDL_WasInit(0) == 0) // Is SDL2 initialized at all? { @@ -74,61 +67,20 @@ static void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device) } else if(!SDL_WasInit(SDL_INIT_AUDIO)) SDL_InitSubSystem(SDL_INIT_AUDIO); - - ATOMIC_INIT(&self->killNow, AL_TRUE); } -static int ALCsdl2Backend_mixerProc(void *ptr) +static void ALCsdl2Backend_audioCallback(void *ptr, Uint8* stream, int len) { ALCsdl2Backend *self = (ALCsdl2Backend*)ptr; ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - struct timespec now, start; - ALuint64 avail, done; - const long restTime = (long)((ALuint64)device->UpdateSize * 1000000000 / - device->Frequency / 2); - - SetRTPriority(); - althrd_setname(althrd_current(), MIXER_THREAD_NAME); - - done = 0; - if(altimespec_get(&start, AL_TIME_UTC) != AL_TIME_UTC) - { - ERR("Failed to get starting time\n"); - return 1; - } - while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) && - ATOMIC_LOAD(&device->Connected, almemory_order_acquire)) - { - if(altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC) - { - ERR("Failed to get current time\n"); - return 1; - } - - avail = (now.tv_sec - start.tv_sec) * device->Frequency; - avail += (ALint64)(now.tv_nsec - start.tv_nsec) * device->Frequency / 1000000000; - if(avail < done) - { - /* Oops, time skipped backwards. Reset the number of samples done - * with one update available since we (likely) just came back from - * sleeping. */ - done = avail - device->UpdateSize; - } - - if(avail-done < device->UpdateSize) - al_nssleep(restTime); - else while(avail-done >= device->UpdateSize) - { - ALCsdl2Backend_lock(self); - aluMixData(device, self->mBuffer, device->UpdateSize); - SDL_QueueAudio(self->deviceID, self->mBuffer, self->mSize); - ALCsdl2Backend_unlock(self); - done += device->UpdateSize; - } - } - - return 0; + ALsizei frameSize = FrameSizeFromDevFmt( + device->FmtChans, device->FmtType, device->AmbiOrder + ); + assert(len % frameSize == 0); + ALCsdl2Backend_lock(self); + aluMixData(device, stream, len / frameSize); + ALCsdl2Backend_unlock(self); } static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name) @@ -140,6 +92,8 @@ static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name) want.format = AUDIO_F32; want.channels = 2; want.samples = device->UpdateSize; + want.callback = ALCsdl2Backend_audioCallback; + want.userdata = self; if(!name) name = SDL_GetAudioDeviceName(0, 0); @@ -161,39 +115,13 @@ static ALCboolean ALCsdl2Backend_reset(ALCsdl2Backend *self) static ALCboolean ALCsdl2Backend_start(ALCsdl2Backend *self) { - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - self->mSize = device->UpdateSize * FrameSizeFromDevFmt( - device->FmtChans, device->FmtType, device->AmbiOrder - ); - self->mBuffer = malloc(self->mSize); - if(!self->mBuffer) - { - ERR("Buffer malloc failed\n"); - return ALC_FALSE; - } - - ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release); - if(althrd_create(&self->thread, ALCsdl2Backend_mixerProc, self) != althrd_success) - { - free(self->mBuffer); - self->mBuffer = NULL; - self->mSize = 0; - return ALC_FALSE; - } SDL_PauseAudioDevice(self->deviceID, 0); return ALC_TRUE; } static void ALCsdl2Backend_stop(ALCsdl2Backend *self) { - int res; - - if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel)) - return; - althrd_join(self->thread, &res); - - free(self->mBuffer); - self->mBuffer = NULL; + SDL_PauseAudioDevice(self->deviceID, 1); if(self->quit) SDL_Quit(); } |