Skip to content
This repository has been archived by the owner on Jan 16, 2025. It is now read-only.

Commit

Permalink
audio: Use a thread and fifo buffer.
Browse files Browse the repository at this point in the history
  • Loading branch information
宋文武 committed Dec 3, 2024
1 parent d144843 commit 908aa01
Showing 1 changed file with 83 additions and 49 deletions.
132 changes: 83 additions & 49 deletions sdl-libretro/audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <sdl/src/audio/SDL_audio_c.h>
#include <sdl/src/audio/SDL_audiodev_c.h>
#include <sdl/src/audio/dummy/SDL_dummyaudio.h>
#include <queues/fifo_queue.h>

/* The tag name used by DUMMY audio */
#define DUMMYAUD_DRIVER_NAME "dummy"
Expand All @@ -16,100 +17,133 @@ static void DUMMYAUD_CloseAudio(_THIS);

static SDL_AudioSpec *_spec = NULL;
static Uint8 *_mixbuf = NULL;
static fifo_buffer_t *_stream = NULL;
static SDL_mutex *_stream_lock = NULL;


/* Audio driver bootstrap functions */
static int DUMMYAUD_Available(void)
{
return 1;
return 1;
}

static void DUMMYAUD_DeleteDevice(SDL_AudioDevice *device)
{
SDL_free(device->hidden);
SDL_free(device);
SDL_free(device->hidden);
SDL_free(device);
}

static SDL_AudioDevice *DUMMYAUD_CreateDevice(int devindex)
{
SDL_AudioDevice *this;

/* Initialize all variables that we clean on shutdown */
this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice));
SDL_AudioDevice *this;

/* Initialize all variables that we clean on shutdown */
this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice));
if (this) {
SDL_memset(this, 0, (sizeof *this));
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc((sizeof *this->hidden));
}
if (this == NULL || this->hidden == NULL) {
SDL_OutOfMemory();
if (this) {
SDL_memset(this, 0, (sizeof *this));
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc((sizeof *this->hidden));
}
if (this == NULL || this->hidden == NULL) {
SDL_OutOfMemory();
if (this) {
SDL_free(this);
}
return 0;
SDL_free(this);
}
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
return 0;
}
SDL_memset(this->hidden, 0, (sizeof *this->hidden));

/* Set the function pointers */
this->OpenAudio = DUMMYAUD_OpenAudio;
this->WaitAudio = DUMMYAUD_WaitAudio;
this->PlayAudio = DUMMYAUD_PlayAudio;
this->GetAudioBuf = DUMMYAUD_GetAudioBuf;
this->CloseAudio = DUMMYAUD_CloseAudio;
/* Set the function pointers */
this->OpenAudio = DUMMYAUD_OpenAudio;
this->WaitAudio = DUMMYAUD_WaitAudio;
this->PlayAudio = DUMMYAUD_PlayAudio;
this->GetAudioBuf = DUMMYAUD_GetAudioBuf;
this->CloseAudio = DUMMYAUD_CloseAudio;

this->free = DUMMYAUD_DeleteDevice;
this->free = DUMMYAUD_DeleteDevice;

return this;
return this;
}

AudioBootStrap DUMMYAUD_bootstrap = {
DUMMYAUD_DRIVER_NAME, "SDL dummy audio driver",
DUMMYAUD_Available, DUMMYAUD_CreateDevice
DUMMYAUD_DRIVER_NAME, "SDL dummy audio driver",
DUMMYAUD_Available, DUMMYAUD_CreateDevice
};


static void DUMMYAUD_WaitAudio(_THIS)
{
SDL_mutexP(_stream_lock);
while (this->enabled && FIFO_WRITE_AVAIL(_stream) < _spec->size) {
SDL_mutexV(_stream_lock);
SDL_Delay(50);
SDL_mutexP(_stream_lock);
}
SDL_mutexV(_stream_lock);
}

static void DUMMYAUD_PlayAudio(_THIS)
{
SDL_mutexP(_stream_lock);
fifo_write(_stream, _mixbuf, _spec->size);
SDL_mutexV(_stream_lock);
}

static Uint8 *DUMMYAUD_GetAudioBuf(_THIS)
{
return NULL;
return _mixbuf;
}

static void DUMMYAUD_CloseAudio(_THIS)
{
if (_mixbuf != NULL) {
SDL_FreeAudioMem(_mixbuf);
_mixbuf = NULL;
}
if (_mixbuf != NULL) {
SDL_FreeAudioMem(_mixbuf);
_mixbuf = NULL;
}
if (_stream != NULL) {
fifo_free(_stream);
_stream = NULL;
};
if (_stream_lock != NULL) {
SDL_DestroyMutex(_stream_lock);
_stream_lock = NULL;
}
}

static int DUMMYAUD_OpenAudio(_THIS, SDL_AudioSpec *spec)
{
spec->samples = spec->freq / 60;
SDL_CalculateAudioSpec(spec);
_mixbuf = SDL_AllocAudioMem(spec->size);
if (_mixbuf == NULL)
return -1;
_mixbuf = SDL_AllocAudioMem(spec->size);
if (_mixbuf == NULL)
return -1;

_stream = fifo_new(spec->size * 2);
if (_stream == NULL)
return -1;

_stream_lock = SDL_CreateMutex();
if (_stream_lock == NULL)
return -1;

_spec = spec;
_spec = spec;

/* Don't spawn thread for SDL_RunAudio */
return 1;
return 0;
}

void SDL_libretro_ProduceAudio(retro_audio_sample_batch_t audio_batch_cb)
{
if (SDL_GetAudioStatus() != SDL_AUDIO_PLAYING)
return;

SDL_LockAudio();
SDL_memset(_mixbuf, 0, _spec->size);
_spec->callback(_spec->userdata, _mixbuf, _spec->size);
audio_batch_cb((const int16_t *)_mixbuf, _spec->samples);
SDL_UnlockAudio();
static int16_t buffer[2048];
static const size_t samples = 44100 / 60;

if (SDL_GetAudioStatus() != SDL_AUDIO_PLAYING)
return;

SDL_mutexP(_stream_lock);
if (FIFO_READ_AVAIL(_stream) < samples * 4) {
// XXX: underrun!
SDL_mutexV(_stream_lock);
return;
}
fifo_read(_stream, buffer, samples * 4);
SDL_mutexV(_stream_lock);
audio_batch_cb(buffer, samples);
}

0 comments on commit 908aa01

Please sign in to comment.