MOve audio drivers to audio/drivers

This commit is contained in:
twinaphex 2015-01-12 05:05:56 +01:00
parent 5f611f7270
commit 1753430d68
22 changed files with 481 additions and 348 deletions

View File

@ -141,7 +141,7 @@ OBJ += frontend/frontend.o \
location/nulllocation.o \ location/nulllocation.o \
camera/nullcamera.o \ camera/nullcamera.o \
gfx/nullgfx.o \ gfx/nullgfx.o \
audio/nullaudio.o \ audio/drivers/nullaudio.o \
input/nullinput.o \ input/nullinput.o \
input/nullinput_joypad.o \ input/nullinput_joypad.o \
input/osk/nullosk.o \ input/osk/nullosk.o \
@ -173,39 +173,39 @@ endif
ifeq ($(HAVE_EMSCRIPTEN), 1) ifeq ($(HAVE_EMSCRIPTEN), 1)
OBJ += frontend/platform/platform_emscripten.o \ OBJ += frontend/platform/platform_emscripten.o \
input/rwebinput_input.o \ input/rwebinput_input.o \
audio/rwebaudio.o \ audio/drivers/rwebaudio.o \
camera/rwebcam.o camera/rwebcam.o
endif endif
# Audio # Audio
# #
ifeq ($(HAVE_COREAUDIO), 1) ifeq ($(HAVE_COREAUDIO), 1)
OBJ += audio/coreaudio.o OBJ += audio/drivers/coreaudio.o
LIBS += -framework CoreServices -framework CoreAudio -framework AudioUnit LIBS += -framework CoreServices -framework CoreAudio -framework AudioUnit
endif endif
ifeq ($(HAVE_OSS), 1) ifeq ($(HAVE_OSS), 1)
OBJ += audio/oss.o OBJ += audio/drivers/oss.o
endif endif
ifeq ($(HAVE_OSS_BSD), 1) ifeq ($(HAVE_OSS_BSD), 1)
OBJ += audio/oss.o OBJ += audio/drivers/oss.o
endif endif
ifeq ($(HAVE_ALSA), 1) ifeq ($(HAVE_ALSA), 1)
OBJ += audio/alsa.o audio/alsathread.o OBJ += audio/drivers/alsa.o audio/drivers/alsathread.o
LIBS += $(ALSA_LIBS) LIBS += $(ALSA_LIBS)
DEFINES += $(ALSA_CFLAGS) DEFINES += $(ALSA_CFLAGS)
endif endif
ifeq ($(HAVE_ROAR), 1) ifeq ($(HAVE_ROAR), 1)
OBJ += audio/roar.o OBJ += audio/drivers/roar.o
LIBS += $(ROAR_LIBS) LIBS += $(ROAR_LIBS)
DEFINES += $(ROAR_CFLAGS) DEFINES += $(ROAR_CFLAGS)
endif endif
ifeq ($(HAVE_AL), 1) ifeq ($(HAVE_AL), 1)
OBJ += audio/openal.o OBJ += audio/drivers/openal.o
ifeq ($(OSX),1) ifeq ($(OSX),1)
LIBS += -framework OpenAL LIBS += -framework OpenAL
else else
@ -214,13 +214,13 @@ ifeq ($(HAVE_AL), 1)
endif endif
ifeq ($(HAVE_JACK),1) ifeq ($(HAVE_JACK),1)
OBJ += audio/jack.o OBJ += audio/drivers/jack.o
LIBS += $(JACK_LIBS) LIBS += $(JACK_LIBS)
DEFINES += $(JACK_CFLAGS) DEFINES += $(JACK_CFLAGS)
endif endif
ifeq ($(HAVE_PULSE), 1) ifeq ($(HAVE_PULSE), 1)
OBJ += audio/pulse.o OBJ += audio/drivers/pulse.o
LIBS += $(PULSE_LIBS) LIBS += $(PULSE_LIBS)
DEFINES += $(PULSE_CFLAGS) DEFINES += $(PULSE_CFLAGS)
endif endif
@ -236,13 +236,13 @@ ifeq ($(HAVE_RSOUND), 1)
endif endif
ifeq ($(HAVE_DSOUND), 1) ifeq ($(HAVE_DSOUND), 1)
OBJ += audio/dsound.o OBJ += audio/drivers/dsound.o
DEFINES += -DHAVE_DSOUND DEFINES += -DHAVE_DSOUND
LIBS += -ldxguid -ldsound LIBS += -ldxguid -ldsound
endif endif
ifeq ($(HAVE_XAUDIO), 1) ifeq ($(HAVE_XAUDIO), 1)
OBJ += audio/xaudio.o audio/xaudio-c/xaudio-c.o OBJ += audio/drivers/xaudio.o audio/xaudio-c/xaudio-c.o
DEFINES += -DHAVE_XAUDIO DEFINES += -DHAVE_XAUDIO
LIBS += -lole32 LIBS += -lole32
endif endif
@ -449,7 +449,7 @@ ifeq ($(HAVE_SDL2), 1)
endif endif
ifeq ($(HAVE_SDL), 1) ifeq ($(HAVE_SDL), 1)
OBJ += gfx/sdl_gfx.o input/sdl_input.o input/sdl_joypad.o audio/sdl_audio.o OBJ += gfx/sdl_gfx.o input/sdl_input.o input/sdl_joypad.o audio/drivers/sdl_audio.o
ifeq ($(HAVE_OPENGL), 1) ifeq ($(HAVE_OPENGL), 1)
OBJ += gfx/context/sdl_gl_ctx.o OBJ += gfx/context/sdl_gl_ctx.o
@ -461,7 +461,7 @@ ifeq ($(HAVE_SDL), 1)
endif endif
ifeq ($(HAVE_SDL2), 1) ifeq ($(HAVE_SDL2), 1)
OBJ += gfx/sdl2_gfx.o input/sdl_input.o input/sdl_joypad.o audio/sdl_audio.o OBJ += gfx/sdl2_gfx.o input/sdl_input.o input/sdl_joypad.o audio/drivers/sdl_audio.o
ifeq ($(HAVE_OPENGL), 1) ifeq ($(HAVE_OPENGL), 1)
OBJ += gfx/context/sdl_gl_ctx.o OBJ += gfx/context/sdl_gl_ctx.o

View File

@ -14,10 +14,10 @@
*/ */
#include "../driver.h" #include "../../driver.h"
#include <stdlib.h> #include <stdlib.h>
#include <alsa/asoundlib.h> #include <alsa/asoundlib.h>
#include "../general.h" #include "../../general.h"
#define TRY_ALSA(x) if (x < 0) { \ #define TRY_ALSA(x) if (x < 0) { \
goto error; \ goto error; \

View File

@ -14,8 +14,8 @@
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "../general.h" #include "../../general.h"
#include "../driver.h" #include "../../driver.h"
#define ALSA_PCM_NEW_HW_PARAMS_API #define ALSA_PCM_NEW_HW_PARAMS_API
#define ALSA_PCM_NEW_SW_PARAMS_API #define ALSA_PCM_NEW_SW_PARAMS_API

View File

@ -15,10 +15,10 @@
*/ */
#include "../driver.h" #include "../../driver.h"
#include <stdlib.h> #include <stdlib.h>
#include <alsa/asoundlib.h> #include <alsa/asoundlib.h>
#include "../general.h" #include "../../general.h"
#include <rthreads/rthreads.h> #include <rthreads/rthreads.h>
#include <queues/fifo_buffer.h> #include <queues/fifo_buffer.h>
@ -284,9 +284,9 @@ static ssize_t alsa_thread_write(void *data, const void *buf, size_t size)
static bool alsa_thread_alive(void *data) static bool alsa_thread_alive(void *data)
{ {
alsa_thread_t *alsa = (alsa_thread_t*)data; alsa_thread_t *alsa = (alsa_thread_t*)data;
if (alsa) if (!alsa)
return !alsa->is_paused; return false;
return false; return !alsa->is_paused;
} }
static bool alsa_thread_stop(void *data) static bool alsa_thread_stop(void *data)

View File

@ -14,9 +14,8 @@
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "../../driver.h"
#include "../driver.h" #include "../../general.h"
#include "../general.h"
#include <queues/fifo_buffer.h> #include <queues/fifo_buffer.h>
#include <stdlib.h> #include <stdlib.h>
#include <boolean.h> #include <boolean.h>
@ -55,6 +54,7 @@ static bool g_interrupted;
static void coreaudio_free(void *data) static void coreaudio_free(void *data)
{ {
coreaudio_t *dev = (coreaudio_t*)data; coreaudio_t *dev = (coreaudio_t*)data;
if (!dev) if (!dev)
return; return;
@ -82,7 +82,10 @@ static OSStatus audio_write_cb(void *userdata,
const AudioTimeStamp *time_stamp, UInt32 bus_number, const AudioTimeStamp *time_stamp, UInt32 bus_number,
UInt32 number_frames, AudioBufferList *io_data) UInt32 number_frames, AudioBufferList *io_data)
{ {
void *outbuf;
unsigned write_avail;
coreaudio_t *dev = (coreaudio_t*)userdata; coreaudio_t *dev = (coreaudio_t*)userdata;
(void)time_stamp; (void)time_stamp;
(void)bus_number; (void)bus_number;
(void)number_frames; (void)number_frames;
@ -92,10 +95,11 @@ static OSStatus audio_write_cb(void *userdata,
if (io_data->mNumberBuffers != 1) if (io_data->mNumberBuffers != 1)
return noErr; return noErr;
unsigned write_avail = io_data->mBuffers[0].mDataByteSize; write_avail = io_data->mBuffers[0].mDataByteSize;
void *outbuf = io_data->mBuffers[0].mData; outbuf = io_data->mBuffers[0].mData;
pthread_mutex_lock(&dev->lock); pthread_mutex_lock(&dev->lock);
if (fifo_read_avail(dev->buffer) < write_avail) if (fifo_read_avail(dev->buffer) < write_avail)
{ {
*action_flags = kAudioUnitRenderAction_OutputIsSilence; *action_flags = kAudioUnitRenderAction_OutputIsSilence;
@ -119,6 +123,8 @@ static OSStatus audio_write_cb(void *userdata,
#ifdef OSX #ifdef OSX
static void choose_output_device(coreaudio_t *dev, const char* device) static void choose_output_device(coreaudio_t *dev, const char* device)
{ {
unsigned i;
AudioDeviceID *devices;
AudioObjectPropertyAddress propaddr = AudioObjectPropertyAddress propaddr =
{ {
kAudioHardwarePropertyDevices, kAudioHardwarePropertyDevices,
@ -126,14 +132,14 @@ static void choose_output_device(coreaudio_t *dev, const char* device)
kAudioObjectPropertyElementMaster kAudioObjectPropertyElementMaster
}; };
UInt32 size = 0; UInt32 size = 0, deviceCount;
if (AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, if (AudioObjectGetPropertyDataSize(kAudioObjectSystemObject,
&propaddr, 0, 0, &size) != noErr) &propaddr, 0, 0, &size) != noErr)
return; return;
UInt32 deviceCount = size / sizeof(AudioDeviceID); deviceCount = size / sizeof(AudioDeviceID);
AudioDeviceID *devices = malloc(size); devices = (AudioDeviceID*)malloc(size);
if (!devices || AudioObjectGetPropertyData(kAudioObjectSystemObject, if (!devices || AudioObjectGetPropertyData(kAudioObjectSystemObject,
&propaddr, 0, 0, &size, devices) != noErr) &propaddr, 0, 0, &size, devices) != noErr)
@ -143,7 +149,7 @@ static void choose_output_device(coreaudio_t *dev, const char* device)
propaddr.mSelector = kAudioDevicePropertyDeviceName; propaddr.mSelector = kAudioDevicePropertyDeviceName;
size = 1024; size = 1024;
for (unsigned i = 0; i < deviceCount; i ++) for (i = 0; i < deviceCount; i ++)
{ {
char device_name[1024]; char device_name[1024];
device_name[0] = 0; device_name[0] = 0;
@ -174,6 +180,10 @@ static void coreaudio_interrupt_listener(void *data, UInt32 interrupt_state)
static void *coreaudio_init(const char *device, static void *coreaudio_init(const char *device,
unsigned rate, unsigned latency) unsigned rate, unsigned latency)
{ {
static bool session_initialized = false;
UInt32 i_size;
(void)session_initialized;
(void)device; (void)device;
coreaudio_t *dev = (coreaudio_t*)calloc(1, sizeof(*dev)); coreaudio_t *dev = (coreaudio_t*)calloc(1, sizeof(*dev));
@ -184,7 +194,6 @@ static void *coreaudio_init(const char *device,
pthread_cond_init(&dev->cond, NULL); pthread_cond_init(&dev->cond, NULL);
#ifdef IOS #ifdef IOS
static bool session_initialized = false;
if (!session_initialized) if (!session_initialized)
{ {
session_initialized = true; session_initialized = true;
@ -249,7 +258,7 @@ static void *coreaudio_init(const char *device,
goto error; goto error;
/* Check returned audio format. */ /* Check returned audio format. */
UInt32 i_size = sizeof(real_desc);; i_size = sizeof(real_desc);;
if (AudioUnitGetProperty(dev->dev, kAudioUnitProperty_StreamFormat, if (AudioUnitGetProperty(dev->dev, kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input, 0, &real_desc, &i_size) != noErr) kAudioUnitScope_Input, 0, &real_desc, &i_size) != noErr)
goto error; goto error;
@ -333,9 +342,11 @@ static ssize_t coreaudio_write(void *data, const void *buf_, size_t size)
while (!g_interrupted && size > 0) while (!g_interrupted && size > 0)
{ {
size_t write_avail;
pthread_mutex_lock(&dev->lock); pthread_mutex_lock(&dev->lock);
size_t write_avail = fifo_write_avail(dev->buffer); write_avail = fifo_write_avail(dev->buffer);
if (write_avail > size) if (write_avail > size)
write_avail = size; write_avail = size;
@ -374,14 +385,16 @@ static void coreaudio_set_nonblock_state(void *data, bool state)
static bool coreaudio_alive(void *data) static bool coreaudio_alive(void *data)
{ {
coreaudio_t *dev = (coreaudio_t*)data; coreaudio_t *dev = (coreaudio_t*)data;
if (dev) if (!dev)
return !dev->is_paused; return false;
return false; return !dev->is_paused;
} }
static bool coreaudio_stop(void *data) static bool coreaudio_stop(void *data)
{ {
coreaudio_t *dev = (coreaudio_t*)data; coreaudio_t *dev = (coreaudio_t*)data;
if (!dev)
return false;
dev->is_paused = (AudioOutputUnitStop(dev->dev) == noErr) ? true : false; dev->is_paused = (AudioOutputUnitStop(dev->dev) == noErr) ? true : false;
return dev->is_paused ? true : false; return dev->is_paused ? true : false;
} }
@ -389,6 +402,8 @@ static bool coreaudio_stop(void *data)
static bool coreaudio_start(void *data) static bool coreaudio_start(void *data)
{ {
coreaudio_t *dev = (coreaudio_t*)data; coreaudio_t *dev = (coreaudio_t*)data;
if (!dev)
return false;
dev->is_paused = (AudioOutputUnitStart(dev->dev) == noErr) ? false : true; dev->is_paused = (AudioOutputUnitStart(dev->dev) == noErr) ? false : true;
return dev->is_paused ? false : true; return dev->is_paused ? false : true;
} }
@ -401,10 +416,13 @@ static bool coreaudio_use_float(void *data)
static size_t coreaudio_write_avail(void *data) static size_t coreaudio_write_avail(void *data)
{ {
size_t avail;
coreaudio_t *dev = (coreaudio_t*)data; coreaudio_t *dev = (coreaudio_t*)data;
pthread_mutex_lock(&dev->lock); pthread_mutex_lock(&dev->lock);
size_t avail = fifo_write_avail(dev->buffer); avail = fifo_write_avail(dev->buffer);
pthread_mutex_unlock(&dev->lock); pthread_mutex_unlock(&dev->lock);
return avail; return avail;
} }

View File

@ -39,7 +39,7 @@ static DSMIXBINVOLUMEPAIR dsmbvp[8] = {
static DSMIXBINS dsmb; static DSMIXBINS dsmb;
#endif #endif
#include "../driver.h" #include "../../driver.h"
#include <stdlib.h> #include <stdlib.h>
#include <boolean.h> #include <boolean.h>
#include <stddef.h> #include <stddef.h>
@ -53,7 +53,7 @@ static DSMIXBINS dsmb;
#endif #endif
#include <dsound.h> #include <dsound.h>
#include <queues/fifo_buffer.h> #include <queues/fifo_buffer.h>
#include "../general.h" #include "../../general.h"
typedef struct dsound typedef struct dsound
{ {
@ -93,21 +93,25 @@ struct audio_lock
DWORD size2; DWORD size2;
}; };
static inline bool grab_region(dsound_t *ds, DWORD write_ptr, struct audio_lock *region) static inline bool grab_region(dsound_t *ds, DWORD write_ptr,
struct audio_lock *region)
{ {
HRESULT res = IDirectSoundBuffer_Lock(ds->dsb, write_ptr, CHUNK_SIZE, &region->chunk1, &region->size1, &region->chunk2, &region->size2, 0); const char *err;
HRESULT res = IDirectSoundBuffer_Lock(ds->dsb, write_ptr, CHUNK_SIZE,
&region->chunk1, &region->size1, &region->chunk2, &region->size2, 0);
if (res == DSERR_BUFFERLOST) if (res == DSERR_BUFFERLOST)
{ {
res = IDirectSoundBuffer_Restore(ds->dsb); res = IDirectSoundBuffer_Restore(ds->dsb);
if (res != DS_OK) if (res != DS_OK)
return false; return false;
res = IDirectSoundBuffer_Lock(ds->dsb, write_ptr, CHUNK_SIZE, &region->chunk1, &region->size1, &region->chunk2, &region->size2, 0); res = IDirectSoundBuffer_Lock(ds->dsb, write_ptr, CHUNK_SIZE,
&region->chunk1, &region->size1, &region->chunk2, &region->size2, 0);
if (res != DS_OK) if (res != DS_OK)
return false; return false;
} }
const char *err;
switch (res) switch (res)
{ {
case DSERR_BUFFERLOST: case DSERR_BUFFERLOST:
@ -143,34 +147,43 @@ static inline void release_region(dsound_t *ds, const struct audio_lock *region)
static DWORD CALLBACK dsound_thread(PVOID data) static DWORD CALLBACK dsound_thread(PVOID data)
{ {
DWORD write_ptr;
dsound_t *ds = (dsound_t*)data; dsound_t *ds = (dsound_t*)data;
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
DWORD write_ptr;
get_positions(ds, NULL, &write_ptr); get_positions(ds, NULL, &write_ptr);
write_ptr = (write_ptr + ds->buffer_size / 2) % ds->buffer_size; write_ptr = (write_ptr + ds->buffer_size / 2) % ds->buffer_size;
while (ds->thread_alive) while (ds->thread_alive)
{ {
DWORD read_ptr; struct audio_lock region;
DWORD read_ptr, avail, fifo_avail;
get_positions(ds, &read_ptr, NULL); get_positions(ds, &read_ptr, NULL);
DWORD avail = write_avail(read_ptr, write_ptr, ds->buffer_size); avail = write_avail(read_ptr, write_ptr, ds->buffer_size);
EnterCriticalSection(&ds->crit); EnterCriticalSection(&ds->crit);
DWORD fifo_avail = fifo_read_avail(ds->buffer); fifo_avail = fifo_read_avail(ds->buffer);
LeaveCriticalSection(&ds->crit); LeaveCriticalSection(&ds->crit);
// No space to write, or we don't have data in our fifo, but we can wait some time before it underruns ...
if (avail < CHUNK_SIZE || ((fifo_avail < CHUNK_SIZE) && (avail < ds->buffer_size / 2))) if (avail < CHUNK_SIZE || ((fifo_avail < CHUNK_SIZE) && (avail < ds->buffer_size / 2)))
{ {
/* No space to write, or we don't have data in our fifo,
* but we can wait some time before it underruns ... */
Sleep(1); Sleep(1);
// We could opt for using the notification interface,
// but it is not guaranteed to work, so use high priority sleeping patterns. :( /* We could opt for using the notification interface,
* but it is not guaranteed to work, so use high
* priority sleeping patterns.
*/
} }
else if (fifo_avail < CHUNK_SIZE) // Got space to write, but nothing in FIFO (underrun), fill block with silence. else if (fifo_avail < CHUNK_SIZE)
{ {
struct audio_lock region; /* Got space to write, but nothing in FIFO (underrun),
* fill block with silence. */
if (!grab_region(ds, write_ptr, &region)) if (!grab_region(ds, write_ptr, &region))
{ {
ds->thread_alive = false; ds->thread_alive = false;
@ -184,9 +197,10 @@ static DWORD CALLBACK dsound_thread(PVOID data)
release_region(ds, &region); release_region(ds, &region);
write_ptr = (write_ptr + region.size1 + region.size2) % ds->buffer_size; write_ptr = (write_ptr + region.size1 + region.size2) % ds->buffer_size;
} }
else // All is good. Pull from it and notify FIFO :D else
{ {
struct audio_lock region; /* All is good. Pull from it and notify FIFO. */
if (!grab_region(ds, write_ptr, &region)) if (!grab_region(ds, write_ptr, &region))
{ {
ds->thread_alive = false; ds->thread_alive = false;
@ -213,13 +227,13 @@ static DWORD CALLBACK dsound_thread(PVOID data)
static void dsound_stop_thread(dsound_t *ds) static void dsound_stop_thread(dsound_t *ds)
{ {
if (ds->thread) if (!ds->thread)
{ return;
ds->thread_alive = false;
WaitForSingleObject(ds->thread, INFINITE); ds->thread_alive = false;
CloseHandle(ds->thread); WaitForSingleObject(ds->thread, INFINITE);
ds->thread = NULL; CloseHandle(ds->thread);
} ds->thread = NULL;
} }
static bool dsound_start_thread(dsound_t *ds) static bool dsound_start_thread(dsound_t *ds)
@ -237,11 +251,12 @@ static bool dsound_start_thread(dsound_t *ds)
static void dsound_clear_buffer(dsound_t *ds) static void dsound_clear_buffer(dsound_t *ds)
{ {
IDirectSoundBuffer_SetCurrentPosition(ds->dsb, 0);
void *ptr; void *ptr;
DWORD size; DWORD size;
IDirectSoundBuffer_SetCurrentPosition(ds->dsb, 0);
if (IDirectSoundBuffer_Lock(ds->dsb, 0, 0, &ptr, &size, NULL, NULL, DSBLOCK_ENTIREBUFFER) == DS_OK) if (IDirectSoundBuffer_Lock(ds->dsb, 0, 0, &ptr, &size,
NULL, NULL, DSBLOCK_ENTIREBUFFER) == DS_OK)
{ {
memset(ptr, 0, size); memset(ptr, 0, size);
IDirectSoundBuffer_Unlock(ds->dsb, ptr, size, NULL, 0); IDirectSoundBuffer_Unlock(ds->dsb, ptr, size, NULL, 0);
@ -251,34 +266,35 @@ static void dsound_clear_buffer(dsound_t *ds)
static void dsound_free(void *data) static void dsound_free(void *data)
{ {
dsound_t *ds = (dsound_t*)data; dsound_t *ds = (dsound_t*)data;
if (ds)
if (!ds)
return;
if (ds->thread)
{ {
if (ds->thread) ds->thread_alive = false;
{ WaitForSingleObject(ds->thread, INFINITE);
ds->thread_alive = false; CloseHandle(ds->thread);
WaitForSingleObject(ds->thread, INFINITE);
CloseHandle(ds->thread);
}
DeleteCriticalSection(&ds->crit);
if (ds->dsb)
{
IDirectSoundBuffer_Stop(ds->dsb);
IDirectSoundBuffer_Release(ds->dsb);
}
if (ds->ds)
IDirectSound_Release(ds->ds);
if (ds->event)
CloseHandle(ds->event);
if (ds->buffer)
fifo_free(ds->buffer);
free(ds);
} }
DeleteCriticalSection(&ds->crit);
if (ds->dsb)
{
IDirectSoundBuffer_Stop(ds->dsb);
IDirectSoundBuffer_Release(ds->dsb);
}
if (ds->ds)
IDirectSound_Release(ds->ds);
if (ds->event)
CloseHandle(ds->event);
if (ds->buffer)
fifo_free(ds->buffer);
free(ds);
} }
struct dsound_dev struct dsound_dev
@ -291,7 +307,9 @@ struct dsound_dev
static BOOL CALLBACK enumerate_cb(LPGUID guid, LPCSTR desc, LPCSTR module, LPVOID context) static BOOL CALLBACK enumerate_cb(LPGUID guid, LPCSTR desc, LPCSTR module, LPVOID context)
{ {
struct dsound_dev *dev = (struct dsound_dev*)context; struct dsound_dev *dev = (struct dsound_dev*)context;
RARCH_LOG("\t%u: %s\n", dev->total_count, desc); RARCH_LOG("\t%u: %s\n", dev->total_count, desc);
if (dev->device == dev->total_count) if (dev->device == dev->total_count)
dev->guid = guid; dev->guid = guid;
dev->total_count++; dev->total_count++;
@ -303,8 +321,8 @@ static void *dsound_init(const char *device, unsigned rate, unsigned latency)
WAVEFORMATEX wfx = {0}; WAVEFORMATEX wfx = {0};
DSBUFFERDESC bufdesc = {0}; DSBUFFERDESC bufdesc = {0};
struct dsound_dev dev = {0}; struct dsound_dev dev = {0};
dsound_t *ds = (dsound_t*)calloc(1, sizeof(*ds)); dsound_t *ds = (dsound_t*)calloc(1, sizeof(*ds));
if (!ds) if (!ds)
goto error; goto error;
@ -384,14 +402,17 @@ error:
static bool dsound_stop(void *data) static bool dsound_stop(void *data)
{ {
dsound_t *ds = (dsound_t*)data; dsound_t *ds = (dsound_t*)data;
dsound_stop_thread(ds); dsound_stop_thread(ds);
ds->is_paused = (IDirectSoundBuffer_Stop(ds->dsb) == DS_OK) ? true : false; ds->is_paused = (IDirectSoundBuffer_Stop(ds->dsb) == DS_OK) ? true : false;
return (ds->is_paused) ? true : false; return (ds->is_paused) ? true : false;
} }
static bool dsound_start(void *data) static bool dsound_start(void *data)
{ {
dsound_t *ds = (dsound_t*)data; dsound_t *ds = (dsound_t*)data;
dsound_clear_buffer(ds); dsound_clear_buffer(ds);
if (!dsound_start_thread(ds)) if (!dsound_start_thread(ds))
@ -404,30 +425,34 @@ static bool dsound_start(void *data)
static bool dsound_alive(void *data) static bool dsound_alive(void *data)
{ {
dsound_t *ds = (dsound_t*)data; dsound_t *ds = (dsound_t*)data;
if (ds)
return !ds->is_paused; if (!ds)
return false; return false;
return !ds->is_paused;
} }
static void dsound_set_nonblock_state(void *data, bool state) static void dsound_set_nonblock_state(void *data, bool state)
{ {
dsound_t *ds = (dsound_t*)data; dsound_t *ds = (dsound_t*)data;
ds->nonblock = state; if (ds)
ds->nonblock = state;
} }
static ssize_t dsound_write(void *data, const void *buf_, size_t size) static ssize_t dsound_write(void *data, const void *buf_, size_t size)
{ {
size_t written = 0;
dsound_t *ds = (dsound_t*)data; dsound_t *ds = (dsound_t*)data;
const uint8_t *buf = (const uint8_t*)buf_; const uint8_t *buf = (const uint8_t*)buf_;
if (!ds->thread_alive) if (!ds->thread_alive)
return -1; return -1;
size_t written = 0;
while (size > 0) while (size > 0)
{ {
size_t avail;
EnterCriticalSection(&ds->crit); EnterCriticalSection(&ds->crit);
size_t avail = fifo_write_avail(ds->buffer); avail = fifo_write_avail(ds->buffer);
if (avail > size) if (avail > size)
avail = size; avail = size;
@ -450,9 +475,11 @@ static ssize_t dsound_write(void *data, const void *buf_, size_t size)
static size_t dsound_write_avail(void *data) static size_t dsound_write_avail(void *data)
{ {
size_t avail;
dsound_t *ds = (dsound_t*)data; dsound_t *ds = (dsound_t*)data;
EnterCriticalSection(&ds->crit); EnterCriticalSection(&ds->crit);
size_t avail = fifo_write_avail(ds->buffer); avail = fifo_write_avail(ds->buffer);
LeaveCriticalSection(&ds->crit); LeaveCriticalSection(&ds->crit);
return avail; return avail;
} }

View File

@ -14,7 +14,7 @@
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "../driver.h" #include "../../driver.h"
#include <stdlib.h> #include <stdlib.h>
#include <boolean.h> #include <boolean.h>
#include "../general.h" #include "../general.h"
@ -27,7 +27,7 @@
#include <cafe/ai.h> #include <cafe/ai.h>
#endif #endif
#include "../gfx/gx/sdk_defines.h" #include "../../gfx/gx/sdk_defines.h"
#define CHUNK_FRAMES 64 #define CHUNK_FRAMES 64
#define CHUNK_SIZE (CHUNK_FRAMES * sizeof(uint32_t)) #define CHUNK_SIZE (CHUNK_FRAMES * sizeof(uint32_t))
@ -63,20 +63,20 @@ static void dma_callback(void)
{ {
gx_audio_t *wa = (gx_audio_t*)gx_audio_data; gx_audio_t *wa = (gx_audio_t*)gx_audio_data;
if (!stop_audio) if (stop_audio)
{ return;
/* Erase last chunk to avoid repeating audio. */
memset(wa->data[wa->dma_busy], 0, CHUNK_SIZE);
wa->dma_busy = wa->dma_next; /* Erase last chunk to avoid repeating audio. */
wa->dma_next = (wa->dma_next + 1) & (BLOCKS - 1); memset(wa->data[wa->dma_busy], 0, CHUNK_SIZE);
DCFlushRange(wa->data[wa->dma_next], CHUNK_SIZE); wa->dma_busy = wa->dma_next;
wa->dma_next = (wa->dma_next + 1) & (BLOCKS - 1);
AIInitDMA((uint32_t)wa->data[wa->dma_next], CHUNK_SIZE); DCFlushRange(wa->data[wa->dma_next], CHUNK_SIZE);
OSSignalCond(wa->cond); AIInitDMA((uint32_t)wa->data[wa->dma_next], CHUNK_SIZE);
}
OSSignalCond(wa->cond);
} }
static void *gx_audio_init(const char *device, static void *gx_audio_init(const char *device,
@ -135,6 +135,7 @@ static ssize_t gx_audio_write(void *data, const void *buf_, size_t size)
while (frames) while (frames)
{ {
size_t to_write = CHUNK_FRAMES - wa->write_ptr; size_t to_write = CHUNK_FRAMES - wa->write_ptr;
if (frames < to_write) if (frames < to_write)
to_write = frames; to_write = frames;
@ -178,15 +179,17 @@ static void gx_audio_set_nonblock_state(void *data, bool state)
{ {
gx_audio_t *wa = (gx_audio_t*)data; gx_audio_t *wa = (gx_audio_t*)data;
if (!wa) if (wa)
return; wa->nonblock = state;
wa->nonblock = state;
} }
static bool gx_audio_start(void *data) static bool gx_audio_start(void *data)
{ {
gx_audio_t *wa = (gx_audio_t*)data; gx_audio_t *wa = (gx_audio_t*)data;
if (!wa)
return false;
AIStartDMA(); AIStartDMA();
wa->is_paused = false; wa->is_paused = false;
return true; return true;
@ -195,9 +198,9 @@ static bool gx_audio_start(void *data)
static bool gx_audio_alive(void *data) static bool gx_audio_alive(void *data)
{ {
gx_audio_t *wa = (gx_audio_t*)data; gx_audio_t *wa = (gx_audio_t*)data;
if (wa) if (!wa)
return !wa->is_paused; return false;
return false; return !wa->is_paused;
} }
static void gx_audio_free(void *data) static void gx_audio_free(void *data)

View File

@ -14,9 +14,9 @@
*/ */
#include "../driver.h" #include "../../driver.h"
#include <stdlib.h> #include <stdlib.h>
#include "../general.h" #include "../../general.h"
#include <jack/jack.h> #include <jack/jack.h>
#include <jack/types.h> #include <jack/types.h>
@ -46,18 +46,18 @@ typedef struct jack
static int process_cb(jack_nframes_t nframes, void *data) static int process_cb(jack_nframes_t nframes, void *data)
{ {
int i; int i;
jack_nframes_t f; jack_nframes_t f, avail[2], min_avail;
jack_t *jd = (jack_t*)data; jack_t *jd = (jack_t*)data;
if (nframes <= 0) if (nframes <= 0)
{ {
pthread_cond_signal(&jd->cond); pthread_cond_signal(&jd->cond);
return 0; return 0;
} }
jack_nframes_t avail[2];
avail[0] = jack_ringbuffer_read_space(jd->buffer[0]); avail[0] = jack_ringbuffer_read_space(jd->buffer[0]);
avail[1] = jack_ringbuffer_read_space(jd->buffer[1]); avail[1] = jack_ringbuffer_read_space(jd->buffer[1]);
jack_nframes_t min_avail = ((avail[0] < avail[1]) ? avail[0] : avail[1]) / sizeof(jack_default_audio_sample_t); min_avail = ((avail[0] < avail[1]) ? avail[0] : avail[1]) / sizeof(jack_default_audio_sample_t);
if (min_avail > nframes) if (min_avail > nframes)
min_avail = nframes; min_avail = nframes;
@ -69,9 +69,7 @@ static int process_cb(jack_nframes_t nframes, void *data)
jack_ringbuffer_read(jd->buffer[i], (char*)out, min_avail * sizeof(jack_default_audio_sample_t)); jack_ringbuffer_read(jd->buffer[i], (char*)out, min_avail * sizeof(jack_default_audio_sample_t));
for (f = min_avail; f < nframes; f++) for (f = min_avail; f < nframes; f++)
{
out[f] = 0.0f; out[f] = 0.0f;
}
} }
pthread_cond_signal(&jd->cond); pthread_cond_signal(&jd->cond);
return 0; return 0;
@ -80,6 +78,10 @@ static int process_cb(jack_nframes_t nframes, void *data)
static void shutdown_cb(void *data) static void shutdown_cb(void *data)
{ {
jack_t *jd = (jack_t*)data; jack_t *jd = (jack_t*)data;
if (!jd)
return;
jd->shutdown = true; jd->shutdown = true;
pthread_cond_signal(&jd->cond); pthread_cond_signal(&jd->cond);
} }
@ -88,8 +90,8 @@ static int parse_ports(char **dest_ports, const char **jports)
{ {
int i; int i;
char *save; char *save;
const char *con = strtok_r(g_settings.audio.device, ",", &save);
int parsed = 0; int parsed = 0;
const char *con = strtok_r(g_settings.audio.device, ",", &save);
if (con) if (con)
dest_ports[parsed++] = strdup(con); dest_ports[parsed++] = strdup(con);
@ -105,11 +107,10 @@ static int parse_ports(char **dest_ports, const char **jports)
static size_t find_buffersize(jack_t *jd, int latency) static size_t find_buffersize(jack_t *jd, int latency)
{ {
int i; int i, buffer_frames, min_buffer_frames, jack_latency = 0;
jack_latency_range_t range;
int frames = latency * g_settings.audio.out_rate / 1000; int frames = latency * g_settings.audio.out_rate / 1000;
jack_latency_range_t range;
int jack_latency = 0;
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
{ {
jack_port_get_latency_range(jd->ports[i], JackPlaybackLatency, &range); jack_port_get_latency_range(jd->ports[i], JackPlaybackLatency, &range);
@ -119,8 +120,9 @@ static size_t find_buffersize(jack_t *jd, int latency)
RARCH_LOG("JACK: Jack latency is %d frames.\n", jack_latency); RARCH_LOG("JACK: Jack latency is %d frames.\n", jack_latency);
int buffer_frames = frames - jack_latency; buffer_frames = frames - jack_latency;
int min_buffer_frames = jack_get_buffer_size(jd->client) * 2; min_buffer_frames = jack_get_buffer_size(jd->client) * 2;
RARCH_LOG("JACK: Minimum buffer size is %d frames.\n", min_buffer_frames); RARCH_LOG("JACK: Minimum buffer size is %d frames.\n", min_buffer_frames);
if (buffer_frames < min_buffer_frames) if (buffer_frames < min_buffer_frames)
@ -132,17 +134,17 @@ static size_t find_buffersize(jack_t *jd, int latency)
static void *ja_init(const char *device, unsigned rate, unsigned latency) static void *ja_init(const char *device, unsigned rate, unsigned latency)
{ {
int i; int i;
const char **jports = NULL;
char *dest_ports[2];
size_t bufsize = 0;
int parsed = 0;
jack_t *jd = (jack_t*)calloc(1, sizeof(jack_t)); jack_t *jd = (jack_t*)calloc(1, sizeof(jack_t));
if (!jd) if (!jd)
return NULL; return NULL;
pthread_cond_init(&jd->cond, NULL); pthread_cond_init(&jd->cond, NULL);
pthread_mutex_init(&jd->cond_lock, NULL); pthread_mutex_init(&jd->cond_lock, NULL);
const char **jports = NULL;
char *dest_ports[2];
size_t bufsize = 0;
int parsed = 0;
jd->client = jack_client_open("RetroArch", JackNullOption, NULL); jd->client = jack_client_open("RetroArch", JackNullOption, NULL);
if (jd->client == NULL) if (jd->client == NULL)
@ -214,12 +216,12 @@ error:
static size_t write_buffer(jack_t *jd, const float *buf, size_t size) static size_t write_buffer(jack_t *jd, const float *buf, size_t size)
{ {
int i; int i;
size_t j; size_t j, frames, written = 0;
jack_default_audio_sample_t out_deinterleaved_buffer[2][AUDIO_CHUNK_SIZE_NONBLOCKING * AUDIO_MAX_RATIO]; jack_default_audio_sample_t out_deinterleaved_buffer[2][AUDIO_CHUNK_SIZE_NONBLOCKING * AUDIO_MAX_RATIO];
size_t frames = FRAMES(size); frames = FRAMES(size);
// Avoid buffer overflow if a DSP plugin generated a huge number of frames /* Avoid buffer overflow if a DSP plugin generated a huge number of frames. */
if (frames > AUDIO_CHUNK_SIZE_NONBLOCKING * AUDIO_MAX_RATIO) if (frames > AUDIO_CHUNK_SIZE_NONBLOCKING * AUDIO_MAX_RATIO)
frames = AUDIO_CHUNK_SIZE_NONBLOCKING * AUDIO_MAX_RATIO; frames = AUDIO_CHUNK_SIZE_NONBLOCKING * AUDIO_MAX_RATIO;
@ -227,21 +229,19 @@ static size_t write_buffer(jack_t *jd, const float *buf, size_t size)
for (j = 0; j < frames; j++) for (j = 0; j < frames; j++)
out_deinterleaved_buffer[i][j] = buf[j * 2 + i]; out_deinterleaved_buffer[i][j] = buf[j * 2 + i];
size_t written = 0;
while (written < frames) while (written < frames)
{ {
size_t avail[2], min_avail, write_frames;
if (jd->shutdown) if (jd->shutdown)
return 0; return 0;
size_t avail[2] = { avail[0] = jack_ringbuffer_write_space(jd->buffer[0]);
jack_ringbuffer_write_space(jd->buffer[0]), avail[1] = jack_ringbuffer_write_space(jd->buffer[1]);
jack_ringbuffer_write_space(jd->buffer[1]),
};
size_t min_avail = avail[0] < avail[1] ? avail[0] : avail[1]; min_avail = avail[0] < avail[1] ? avail[0] : avail[1];
min_avail /= sizeof(float); min_avail /= sizeof(float);
size_t write_frames = frames - written > min_avail ? min_avail : frames - written; write_frames = frames - written > min_avail ? min_avail : frames - written;
if (write_frames > 0) if (write_frames > 0)
{ {
@ -284,15 +284,16 @@ static bool ja_stop(void *data)
static bool ja_alive(void *data) static bool ja_alive(void *data)
{ {
jack_t *jd = (jack_t*)data; jack_t *jd = (jack_t*)data;
if (jd) if (!jd)
return !jd->is_paused; return false;
return false; return !jd->is_paused;
} }
static void ja_set_nonblock_state(void *data, bool state) static void ja_set_nonblock_state(void *data, bool state)
{ {
jack_t *jd = (jack_t*)data; jack_t *jd = (jack_t*)data;
jd->nonblock = state; if (jd)
jd->nonblock = state;
} }
static bool ja_start(void *data) static bool ja_start(void *data)

View File

@ -13,8 +13,8 @@
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "../general.h" #include "../../general.h"
#include "../driver.h" #include "../../driver.h"
static void *null_audio_init(const char *device, unsigned rate, unsigned latency) static void *null_audio_init(const char *device, unsigned rate, unsigned latency)
{ {

View File

@ -13,8 +13,8 @@
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "../driver.h" #include "../../driver.h"
#include "../general.h" #include "../../general.h"
#ifdef __APPLE__ #ifdef __APPLE__
#include <OpenAL/al.h> #include <OpenAL/al.h>
@ -56,6 +56,7 @@ typedef struct al
static void al_free(void *data) static void al_free(void *data)
{ {
al_t *al = (al_t*)data; al_t *al = (al_t*)data;
if (!al) if (!al)
return; return;
@ -78,24 +79,27 @@ static void al_free(void *data)
static void *al_init(const char *device, unsigned rate, unsigned latency) static void *al_init(const char *device, unsigned rate, unsigned latency)
{ {
al_t *al;
(void)device; (void)device;
al_t *al = (al_t*)calloc(1, sizeof(al_t));
al = (al_t*)calloc(1, sizeof(al_t));
if (!al) if (!al)
return NULL; return NULL;
al->handle = alcOpenDevice(NULL); al->handle = alcOpenDevice(NULL);
if (al->handle == NULL) if (!al->handle)
goto error; goto error;
al->ctx = alcCreateContext(al->handle, NULL); al->ctx = alcCreateContext(al->handle, NULL);
if (al->ctx == NULL) if (!al->ctx)
goto error; goto error;
alcMakeContextCurrent(al->ctx); alcMakeContextCurrent(al->ctx);
al->rate = rate; al->rate = rate;
// We already use one buffer for tmpbuf. /* We already use one buffer for tmpbuf. */
al->num_buffers = (latency * rate * 2 * sizeof(int16_t)) / (1000 * BUFSIZE) - 1; al->num_buffers = (latency * rate * 2 * sizeof(int16_t)) / (1000 * BUFSIZE) - 1;
if (al->num_buffers < 2) if (al->num_buffers < 2)
al->num_buffers = 2; al->num_buffers = 2;
@ -126,14 +130,12 @@ static bool al_unqueue_buffers(al_t *al)
alGetSourcei(al->source, AL_BUFFERS_PROCESSED, &val); alGetSourcei(al->source, AL_BUFFERS_PROCESSED, &val);
if (val > 0) if (val <= 0)
{ return false;
alSourceUnqueueBuffers(al->source, val, &al->res_buf[al->res_ptr]);
al->res_ptr += val;
return true;
}
return false; alSourceUnqueueBuffers(al->source, val, &al->res_buf[al->res_ptr]);
al->res_ptr += val;
return true;
} }
static bool al_get_buffer(al_t *al, ALuint *buffer) static bool al_get_buffer(al_t *al, ALuint *buffer)
@ -169,11 +171,14 @@ static ssize_t al_write(void *data, const void *buf_, size_t size)
{ {
al_t *al = (al_t*)data; al_t *al = (al_t*)data;
const uint8_t *buf = (const uint8_t*)buf_; const uint8_t *buf = (const uint8_t*)buf_;
size_t written = 0; size_t written = 0;
while (size) while (size)
{ {
ALint val;
ALuint buffer;
size_t rc = al_fill_internal_buf(al, buf, size); size_t rc = al_fill_internal_buf(al, buf, size);
written += rc; written += rc;
buf += rc; buf += rc;
size -= rc; size -= rc;
@ -181,7 +186,6 @@ static ssize_t al_write(void *data, const void *buf_, size_t size)
if (al->tmpbuf_ptr != BUFSIZE) if (al->tmpbuf_ptr != BUFSIZE)
break; break;
ALuint buffer;
if (!al_get_buffer(al, &buffer)) if (!al_get_buffer(al, &buffer))
break; break;
@ -191,7 +195,6 @@ static ssize_t al_write(void *data, const void *buf_, size_t size)
if (alGetError() != AL_NO_ERROR) if (alGetError() != AL_NO_ERROR)
return -1; return -1;
ALint val;
alGetSourcei(al->source, AL_SOURCE_STATE, &val); alGetSourcei(al->source, AL_SOURCE_STATE, &val);
if (val != AL_PLAYING) if (val != AL_PLAYING)
alSourcePlay(al->source); alSourcePlay(al->source);
@ -214,15 +217,16 @@ static bool al_stop(void *data)
static bool al_alive(void *data) static bool al_alive(void *data)
{ {
al_t *al = (al_t*)data; al_t *al = (al_t*)data;
if (al) if (!al)
return !al->is_paused; return false;
return false; return !al->is_paused;
} }
static void al_set_nonblock_state(void *data, bool state) static void al_set_nonblock_state(void *data, bool state)
{ {
al_t *al = (al_t*)data; al_t *al = (al_t*)data;
al->nonblock = state; if (al)
al->nonblock = state;
} }
static bool al_start(void *data) static bool al_start(void *data)
@ -243,7 +247,7 @@ static size_t al_write_avail(void *data)
static size_t al_buffer_size(void *data) static size_t al_buffer_size(void *data)
{ {
al_t *al = (al_t*)data; al_t *al = (al_t*)data;
return (al->num_buffers + 1) * BUFSIZE; // Also got tmpbuf. return (al->num_buffers + 1) * BUFSIZE; /* Also got tmpbuf. */
} }
static bool al_use_float(void *data) static bool al_use_float(void *data)

View File

@ -14,8 +14,8 @@
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "../driver.h" #include "../../driver.h"
#include "../general.h" #include "../../general.h"
#include <rthreads/rthreads.h> #include <rthreads/rthreads.h>
#include <SLES/OpenSLES.h> #include <SLES/OpenSLES.h>
@ -23,7 +23,7 @@
#include <SLES/OpenSLES_Android.h> #include <SLES/OpenSLES_Android.h>
#endif #endif
// Helper macros, COM-style! /* Helper macros, COM-style. */
#define SLObjectItf_Realize(a, ...) ((*(a))->Realize(a, __VA_ARGS__)) #define SLObjectItf_Realize(a, ...) ((*(a))->Realize(a, __VA_ARGS__))
#define SLObjectItf_GetInterface(a, ...) ((*(a))->GetInterface(a, __VA_ARGS__)) #define SLObjectItf_GetInterface(a, ...) ((*(a))->GetInterface(a, __VA_ARGS__))
#define SLObjectItf_Destroy(a) ((*(a))->Destroy((a))) #define SLObjectItf_Destroy(a) ((*(a))->Destroy((a)))
@ -100,20 +100,23 @@ static void sl_free(void *data)
static void *sl_init(const char *device, unsigned rate, unsigned latency) static void *sl_init(const char *device, unsigned rate, unsigned latency)
{ {
unsigned i; unsigned i;
(void)device; SLInterfaceID id;
SLboolean req;
SLresult res;
sl_t *sl;
SLDataFormat_PCM fmt_pcm = {0}; SLDataFormat_PCM fmt_pcm = {0};
SLDataSource audio_src = {0}; SLDataSource audio_src = {0};
SLDataSink audio_sink = {0}; SLDataSink audio_sink = {0};
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {0}; SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {0};
SLDataLocator_OutputMix loc_outmix = {0}; SLDataLocator_OutputMix loc_outmix = {0};
SLInterfaceID id = SL_IID_ANDROIDSIMPLEBUFFERQUEUE; (void)device;
SLboolean req = SL_BOOLEAN_TRUE;
SLresult res = 0; id = SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
sl_t *sl = (sl_t*)calloc(1, sizeof(sl_t)); req = SL_BOOLEAN_TRUE;
res = 0;
sl = (sl_t*)calloc(1, sizeof(sl_t));
if (!sl) if (!sl)
goto error; goto error;
@ -154,7 +157,7 @@ static void *sl_init(const char *device, unsigned rate, unsigned latency)
fmt_pcm.bitsPerSample = 16; fmt_pcm.bitsPerSample = 16;
fmt_pcm.containerSize = 16; fmt_pcm.containerSize = 16;
fmt_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; fmt_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
fmt_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; // Android only. fmt_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; /* Android only. */
audio_src.pLocator = &loc_bufq; audio_src.pLocator = &loc_bufq;
audio_src.pFormat = &fmt_pcm; audio_src.pFormat = &fmt_pcm;
@ -180,7 +183,7 @@ static void *sl_init(const char *device, unsigned rate, unsigned latency)
(*sl->buffer_queue)->RegisterCallback(sl->buffer_queue, opensl_callback, sl); (*sl->buffer_queue)->RegisterCallback(sl->buffer_queue, opensl_callback, sl);
// Enqueue a bit to get stuff rolling. /* Enqueue a bit to get stuff rolling. */
sl->buffered_blocks = sl->buf_count; sl->buffered_blocks = sl->buf_count;
sl->buffer_index = 0; sl->buffer_index = 0;
for (i = 0; i < sl->buf_count; i++) for (i = 0; i < sl->buf_count; i++)
@ -207,15 +210,16 @@ static bool sl_stop(void *data)
static bool sl_alive(void *data) static bool sl_alive(void *data)
{ {
sl_t *sl = (sl_t*)data; sl_t *sl = (sl_t*)data;
if (sl) if (!sl)
return !sl->is_paused; return false;
return false; return !sl->is_paused;
} }
static void sl_set_nonblock_state(void *data, bool state) static void sl_set_nonblock_state(void *data, bool state)
{ {
sl_t *sl = (sl_t*)data; sl_t *sl = (sl_t*)data;
sl->nonblock = state; if (sl)
sl->nonblock = state;
} }
static bool sl_start(void *data) static bool sl_start(void *data)
@ -229,12 +233,13 @@ static bool sl_start(void *data)
static ssize_t sl_write(void *data, const void *buf_, size_t size) static ssize_t sl_write(void *data, const void *buf_, size_t size)
{ {
sl_t *sl = (sl_t*)data; sl_t *sl = (sl_t*)data;
size_t written = 0; size_t written = 0;
const uint8_t *buf = (const uint8_t*)buf_; const uint8_t *buf = (const uint8_t*)buf_;
while (size) while (size)
{ {
size_t avail_write;
if (sl->nonblock) if (sl->nonblock)
{ {
if (sl->buffered_blocks == sl->buf_count) if (sl->buffered_blocks == sl->buf_count)
@ -248,7 +253,8 @@ static ssize_t sl_write(void *data, const void *buf_, size_t size)
slock_unlock(sl->lock); slock_unlock(sl->lock);
} }
size_t avail_write = min(sl->buf_size - sl->buffer_ptr, size); avail_write = min(sl->buf_size - sl->buffer_ptr, size);
if (avail_write) if (avail_write)
{ {
memcpy(sl->buffer[sl->buffer_index] + sl->buffer_ptr, buf, avail_write); memcpy(sl->buffer[sl->buffer_index] + sl->buffer_ptr, buf, avail_write);

View File

@ -17,8 +17,8 @@
#include "config.h" #include "config.h"
#endif #endif
#include "driver.h" #include "../../driver.h"
#include "general.h" #include "../../general.h"
#include <stdlib.h> #include <stdlib.h>
#ifdef HAVE_OSS_BSD #ifdef HAVE_OSS_BSD
@ -43,7 +43,9 @@ static bool oss_is_paused;
static void *oss_init(const char *device, unsigned rate, unsigned latency) static void *oss_init(const char *device, unsigned rate, unsigned latency)
{ {
int frags, frag, channels, format, new_rate;
int *fd = (int*)calloc(1, sizeof(int)); int *fd = (int*)calloc(1, sizeof(int));
if (fd == NULL) if (fd == NULL)
return NULL; return NULL;
@ -59,15 +61,14 @@ static void *oss_init(const char *device, unsigned rate, unsigned latency)
return NULL; return NULL;
} }
int frags = (latency * rate * 4) / (1000 * (1 << 10)); frags = (latency * rate * 4) / (1000 * (1 << 10));
int frag = (frags << 16) | 10; frag = (frags << 16) | 10;
if (ioctl(*fd, SNDCTL_DSP_SETFRAGMENT, &frag) < 0) if (ioctl(*fd, SNDCTL_DSP_SETFRAGMENT, &frag) < 0)
RARCH_WARN("Cannot set fragment sizes. Latency might not be as expected ...\n"); RARCH_WARN("Cannot set fragment sizes. Latency might not be as expected ...\n");
int channels = 2; channels = 2;
int format = is_little_endian() ? format = is_little_endian() ? AFMT_S16_LE : AFMT_S16_BE;
AFMT_S16_LE : AFMT_S16_BE;
if (ioctl(*fd, SNDCTL_DSP_CHANNELS, &channels) < 0) if (ioctl(*fd, SNDCTL_DSP_CHANNELS, &channels) < 0)
{ {
@ -85,7 +86,8 @@ static void *oss_init(const char *device, unsigned rate, unsigned latency)
return NULL; return NULL;
} }
int new_rate = rate; new_rate = rate;
if (ioctl(*fd, SNDCTL_DSP_SPEED, &new_rate) < 0) if (ioctl(*fd, SNDCTL_DSP_SPEED, &new_rate) < 0)
{ {
close(*fd); close(*fd);
@ -105,12 +107,12 @@ static void *oss_init(const char *device, unsigned rate, unsigned latency)
static ssize_t oss_write(void *data, const void *buf, size_t size) static ssize_t oss_write(void *data, const void *buf, size_t size)
{ {
ssize_t ret;
int *fd = (int*)data; int *fd = (int*)data;
if (size == 0) if (size == 0)
return 0; return 0;
ssize_t ret;
if ((ret = write(*fd, buf, size)) < 0) if ((ret = write(*fd, buf, size)) < 0)
{ {
if (errno == EAGAIN && (fcntl(*fd, F_GETFL) & O_NONBLOCK)) if (errno == EAGAIN && (fcntl(*fd, F_GETFL) & O_NONBLOCK))
@ -125,6 +127,7 @@ static ssize_t oss_write(void *data, const void *buf, size_t size)
static bool oss_stop(void *data) static bool oss_stop(void *data)
{ {
int *fd = (int*)data; int *fd = (int*)data;
ioctl(*fd, SNDCTL_DSP_RESET, 0); ioctl(*fd, SNDCTL_DSP_RESET, 0);
oss_is_paused = true; oss_is_paused = true;
return true; return true;
@ -145,8 +148,9 @@ static bool oss_alive(void *data)
static void oss_set_nonblock_state(void *data, bool state) static void oss_set_nonblock_state(void *data, bool state)
{ {
int *fd = (int*)data;
int rc; int rc;
int *fd = (int*)data;
if (state) if (state)
rc = fcntl(*fd, F_SETFL, fcntl(*fd, F_GETFL) | O_NONBLOCK); rc = fcntl(*fd, F_SETFL, fcntl(*fd, F_GETFL) | O_NONBLOCK);
else else

View File

@ -46,17 +46,16 @@ static void event_loop(void *data)
static void event_loop(uint64_t data) static void event_loop(uint64_t data)
#endif #endif
{ {
ps3_audio_t *aud = data; float out_tmp[CELL_AUDIO_BLOCK_SAMPLES * AUDIO_CHANNELS]
__attribute__((aligned(16)));
sys_event_queue_t id; sys_event_queue_t id;
sys_ipc_key_t key; sys_ipc_key_t key;
sys_event_t event; sys_event_t event;
ps3_audio_t *aud = data;
cellAudioCreateNotifyEventQueue(&id, &key); cellAudioCreateNotifyEventQueue(&id, &key);
cellAudioSetNotifyEventQueue(key); cellAudioSetNotifyEventQueue(key);
float out_tmp[CELL_AUDIO_BLOCK_SAMPLES * AUDIO_CHANNELS]
__attribute__((aligned(16)));
while (!aud->quit_thread) while (!aud->quit_thread)
{ {
sys_event_queue_receive(id, &event, SYS_NO_TIMEOUT); sys_event_queue_receive(id, &event, SYS_NO_TIMEOUT);
@ -80,16 +79,19 @@ static void event_loop(uint64_t data)
static void *ps3_audio_init(const char *device, static void *ps3_audio_init(const char *device,
unsigned rate, unsigned latency) unsigned rate, unsigned latency)
{ {
CellAudioPortParam params;
ps3_audio_t *data;
(void)latency; (void)latency;
(void)device; (void)device;
(void)rate; (void)rate;
ps3_audio_t *data = calloc(1, sizeof(*data)); data = calloc(1, sizeof(*data));
if (!data) if (!data)
return NULL; return NULL;
CellAudioPortParam params;
cellAudioInit(); cellAudioInit();
params.numChannels = AUDIO_CHANNELS; params.numChannels = AUDIO_CHANNELS;
params.numBlocks = AUDIO_BLOCKS; params.numBlocks = AUDIO_BLOCKS;
#ifdef HAVE_HEADSET #ifdef HAVE_HEADSET
@ -151,15 +153,14 @@ static ssize_t ps3_audio_write(void *data, const void *buf, size_t size)
if (fifo_write_avail(aud->buffer) < size) if (fifo_write_avail(aud->buffer) < size)
return 0; return 0;
} }
else
{ while (fifo_write_avail(aud->buffer) < size)
while (fifo_write_avail(aud->buffer) < size) sys_lwcond_wait(&aud->cond, 0);
sys_lwcond_wait(&aud->cond, 0);
}
sys_lwmutex_lock(&aud->lock, SYS_NO_TIMEOUT); sys_lwmutex_lock(&aud->lock, SYS_NO_TIMEOUT);
fifo_write(aud->buffer, buf, size); fifo_write(aud->buffer, buf, size);
sys_lwmutex_unlock(&aud->lock); sys_lwmutex_unlock(&aud->lock);
return size; return size;
} }
@ -188,13 +189,16 @@ static bool ps3_audio_start(void *data)
static bool ps3_audio_alive(void *data) static bool ps3_audio_alive(void *data)
{ {
ps3_audio_t *aud = data; ps3_audio_t *aud = data;
if (!aud)
return false;
return aud->started; return aud->started;
} }
static void ps3_audio_set_nonblock_state(void *data, bool toggle) static void ps3_audio_set_nonblock_state(void *data, bool toggle)
{ {
ps3_audio_t *aud = data; ps3_audio_t *aud = data;
aud->nonblocking = toggle; if (aud)
aud->nonblocking = toggle;
} }
static void ps3_audio_free(void *data) static void ps3_audio_free(void *data)

View File

@ -15,8 +15,8 @@
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "../general.h" #include "../../general.h"
#include "../driver.h" #include "../../driver.h"
#include <pspkernel.h> #include <pspkernel.h>
#include <pspaudio.h> #include <pspaudio.h>
@ -71,10 +71,12 @@ static int audioMainLoop(SceSize args, void* argp)
static void *psp_audio_init(const char *device, static void *psp_audio_init(const char *device,
unsigned rate, unsigned latency) unsigned rate, unsigned latency)
{ {
psp1_audio_t* psp;
(void)device; (void)device;
(void)latency; (void)latency;
psp1_audio_t* psp = (psp1_audio_t*)calloc(1, sizeof(psp1_audio_t)); psp = (psp1_audio_t*)calloc(1, sizeof(psp1_audio_t));
if (!psp) if (!psp)
return NULL; return NULL;
@ -103,12 +105,13 @@ static void *psp_audio_init(const char *device,
static void psp_audio_free(void *data) static void psp_audio_free(void *data)
{ {
SceUInt timeout = 100000;
psp1_audio_t* psp = (psp1_audio_t*)data; psp1_audio_t* psp = (psp1_audio_t*)data;
if(!psp) if(!psp)
return; return;
psp->running = false; psp->running = false;
SceUInt timeout = 100000;
sceKernelWaitThreadEnd(psp->thread, &timeout); sceKernelWaitThreadEnd(psp->thread, &timeout);
sceKernelDeleteThread(psp->thread); sceKernelDeleteThread(psp->thread);
@ -153,14 +156,15 @@ static ssize_t psp_audio_write(void *data, const void *buf, size_t size)
static bool psp_audio_alive(void *data) static bool psp_audio_alive(void *data)
{ {
psp1_audio_t* psp = (psp1_audio_t*)data; psp1_audio_t* psp = (psp1_audio_t*)data;
if (psp) if (!psp)
return psp->running; return false;
return false; return psp->running;
} }
static bool psp_audio_stop(void *data) static bool psp_audio_stop(void *data)
{ {
SceKernelThreadRunStatus runStatus; SceKernelThreadRunStatus runStatus;
SceUInt timeout = 100000;
psp1_audio_t* psp = (psp1_audio_t*)data; psp1_audio_t* psp = (psp1_audio_t*)data;
runStatus.size = sizeof(SceKernelThreadRunStatus); runStatus.size = sizeof(SceKernelThreadRunStatus);
@ -172,7 +176,6 @@ static bool psp_audio_stop(void *data)
return false; return false;
psp->running = false; psp->running = false;
SceUInt timeout = 100000;
sceKernelWaitThreadEnd(psp->thread, &timeout); sceKernelWaitThreadEnd(psp->thread, &timeout);
return true; return true;
@ -201,7 +204,8 @@ static bool psp_audio_start(void *data)
static void psp_audio_set_nonblock_state(void *data, bool toggle) static void psp_audio_set_nonblock_state(void *data, bool toggle)
{ {
psp1_audio_t* psp = (psp1_audio_t*)data; psp1_audio_t* psp = (psp1_audio_t*)data;
psp->nonblocking = toggle; if (psp)
psp->nonblocking = toggle;
} }
static bool psp_audio_use_float(void *data) static bool psp_audio_use_float(void *data)

View File

@ -14,8 +14,8 @@
*/ */
#include "driver.h" #include "../../driver.h"
#include "general.h" #include "../../general.h"
#include <pulse/pulseaudio.h> #include <pulse/pulseaudio.h>
#include <boolean.h> #include <boolean.h>
#include <string.h> #include <string.h>
@ -35,28 +35,29 @@ typedef struct
static void pulse_free(void *data) static void pulse_free(void *data)
{ {
pa_t *pa = (pa_t*)data; pa_t *pa = (pa_t*)data;
if (pa)
if (!pa)
return;
if (pa->mainloop)
pa_threaded_mainloop_stop(pa->mainloop);
if (pa->stream)
{ {
if (pa->mainloop) pa_stream_disconnect(pa->stream);
pa_threaded_mainloop_stop(pa->mainloop); pa_stream_unref(pa->stream);
if (pa->stream)
{
pa_stream_disconnect(pa->stream);
pa_stream_unref(pa->stream);
}
if (pa->context)
{
pa_context_disconnect(pa->context);
pa_context_unref(pa->context);
}
if (pa->mainloop)
pa_threaded_mainloop_free(pa->mainloop);
free(pa);
} }
if (pa->context)
{
pa_context_disconnect(pa->context);
pa_context_unref(pa->context);
}
if (pa->mainloop)
pa_threaded_mainloop_free(pa->mainloop);
free(pa);
} }
static void stream_success_cb(pa_stream *s, int success, void *data) static void stream_success_cb(pa_stream *s, int success, void *data)
@ -70,6 +71,7 @@ static void stream_success_cb(pa_stream *s, int success, void *data)
static void context_state_cb(pa_context *c, void *data) static void context_state_cb(pa_context *c, void *data)
{ {
pa_t *pa = (pa_t*)data; pa_t *pa = (pa_t*)data;
switch (pa_context_get_state(c)) switch (pa_context_get_state(c))
{ {
case PA_CONTEXT_READY: case PA_CONTEXT_READY:
@ -85,6 +87,7 @@ static void context_state_cb(pa_context *c, void *data)
static void stream_state_cb(pa_stream *s, void *data) static void stream_state_cb(pa_stream *s, void *data)
{ {
pa_t *pa = (pa_t*)data; pa_t *pa = (pa_t*)data;
switch (pa_stream_get_state(s)) switch (pa_stream_get_state(s))
{ {
case PA_STREAM_READY: case PA_STREAM_READY:
@ -99,23 +102,29 @@ static void stream_state_cb(pa_stream *s, void *data)
static void stream_request_cb(pa_stream *s, size_t length, void *data) static void stream_request_cb(pa_stream *s, size_t length, void *data)
{ {
pa_t *pa = (pa_t*)data;
(void)length; (void)length;
(void)s; (void)s;
pa_t *pa = (pa_t*)data;
pa_threaded_mainloop_signal(pa->mainloop, 0); pa_threaded_mainloop_signal(pa->mainloop, 0);
} }
static void stream_latency_update_cb(pa_stream *s, void *data) static void stream_latency_update_cb(pa_stream *s, void *data)
{ {
(void)s;
pa_t *pa = (pa_t*)data; pa_t *pa = (pa_t*)data;
(void)s;
pa_threaded_mainloop_signal(pa->mainloop, 0); pa_threaded_mainloop_signal(pa->mainloop, 0);
} }
static void underrun_update_cb(pa_stream *s, void *data) static void underrun_update_cb(pa_stream *s, void *data)
{ {
(void)s;
pa_t *pa = (pa_t*)data; pa_t *pa = (pa_t*)data;
(void)s;
RARCH_LOG("[PulseAudio]: Underrun (Buffer: %u, Writable size: %u).\n", RARCH_LOG("[PulseAudio]: Underrun (Buffer: %u, Writable size: %u).\n",
(unsigned)pa->buffer_size, (unsigned)pa->buffer_size,
(unsigned)pa_stream_writable_size(pa->stream)); (unsigned)pa_stream_writable_size(pa->stream));
@ -133,11 +142,14 @@ static void buffer_attr_cb(pa_stream *s, void *data)
static void *pulse_init(const char *device, unsigned rate, unsigned latency) static void *pulse_init(const char *device, unsigned rate, unsigned latency)
{ {
const pa_buffer_attr *server_attr = NULL;
pa_sample_spec spec; pa_sample_spec spec;
memset(&spec, 0, sizeof(spec)); pa_t *pa;
pa_buffer_attr buffer_attr = {0}; pa_buffer_attr buffer_attr = {0};
pa_t *pa = (pa_t*)calloc(1, sizeof(*pa)); const pa_buffer_attr *server_attr = NULL;
memset(&spec, 0, sizeof(spec));
pa = (pa_t*)calloc(1, sizeof(*pa));
if (!pa) if (!pa)
goto error; goto error;
@ -217,13 +229,13 @@ static ssize_t pulse_write(void *data, const void *buf_, size_t size)
{ {
pa_t *pa = (pa_t*)data; pa_t *pa = (pa_t*)data;
const uint8_t *buf = (const uint8_t*)buf_; const uint8_t *buf = (const uint8_t*)buf_;
size_t written = 0; size_t written = 0;
pa_threaded_mainloop_lock(pa->mainloop); pa_threaded_mainloop_lock(pa->mainloop);
while (size) while (size)
{ {
size_t writable = pa_stream_writable_size(pa->stream); size_t writable = pa_stream_writable_size(pa->stream);
writable = min(size, writable); writable = min(size, writable);
if (writable) if (writable)
@ -246,13 +258,16 @@ static ssize_t pulse_write(void *data, const void *buf_, size_t size)
static bool pulse_stop(void *data) static bool pulse_stop(void *data)
{ {
RARCH_LOG("[PulseAudio]: Pausing.\n"); bool ret;
pa_t *pa = (pa_t*)data; pa_t *pa = (pa_t*)data;
pa->success = true; // In case of spurious wakeup. Not critical.
RARCH_LOG("[PulseAudio]: Pausing.\n");
pa->success = true; /* In case of spurious wakeup. Not critical. */
pa_threaded_mainloop_lock(pa->mainloop); pa_threaded_mainloop_lock(pa->mainloop);
pa_stream_cork(pa->stream, true, stream_success_cb, pa); pa_stream_cork(pa->stream, true, stream_success_cb, pa);
pa_threaded_mainloop_wait(pa->mainloop); pa_threaded_mainloop_wait(pa->mainloop);
bool ret = pa->success; ret = pa->success;
pa_threaded_mainloop_unlock(pa->mainloop); pa_threaded_mainloop_unlock(pa->mainloop);
pa->is_paused = true; pa->is_paused = true;
return ret; return ret;
@ -261,20 +276,24 @@ static bool pulse_stop(void *data)
static bool pulse_alive(void *data) static bool pulse_alive(void *data)
{ {
pa_t *pa = (pa_t*)data; pa_t *pa = (pa_t*)data;
if (pa)
return !pa->is_paused; if (!pa)
return false; return false;
return !pa->is_paused;
} }
static bool pulse_start(void *data) static bool pulse_start(void *data)
{ {
RARCH_LOG("[PulseAudio]: Unpausing.\n"); bool ret;
pa_t *pa = (pa_t*)data; pa_t *pa = (pa_t*)data;
pa->success = true; // In case of spurious wakeup. Not critical.
RARCH_LOG("[PulseAudio]: Unpausing.\n");
pa->success = true; /* In case of spurious wakeup. Not critical. */
pa_threaded_mainloop_lock(pa->mainloop); pa_threaded_mainloop_lock(pa->mainloop);
pa_stream_cork(pa->stream, false, stream_success_cb, pa); pa_stream_cork(pa->stream, false, stream_success_cb, pa);
pa_threaded_mainloop_wait(pa->mainloop); pa_threaded_mainloop_wait(pa->mainloop);
bool ret = pa->success; ret = pa->success;
pa_threaded_mainloop_unlock(pa->mainloop); pa_threaded_mainloop_unlock(pa->mainloop);
pa->is_paused = false; pa->is_paused = false;
return ret; return ret;
@ -283,7 +302,8 @@ static bool pulse_start(void *data)
static void pulse_set_nonblock_state(void *data, bool state) static void pulse_set_nonblock_state(void *data, bool state)
{ {
pa_t *pa = (pa_t*)data; pa_t *pa = (pa_t*)data;
pa->nonblock = state; if (pa)
pa->nonblock = state;
} }
static bool pulse_use_float(void *data) static bool pulse_use_float(void *data)
@ -294,10 +314,12 @@ static bool pulse_use_float(void *data)
static size_t pulse_write_avail(void *data) static size_t pulse_write_avail(void *data)
{ {
size_t length;
pa_t *pa = (pa_t*)data; pa_t *pa = (pa_t*)data;
pa_threaded_mainloop_lock(pa->mainloop); pa_threaded_mainloop_lock(pa->mainloop);
size_t length = pa_stream_writable_size(pa->stream); length = pa_stream_writable_size(pa->stream);
g_extern.audio_data.driver_buffer_size = pa->buffer_size; // Can change spuriously. g_extern.audio_data.driver_buffer_size = pa->buffer_size; /* Can change spuriously. */
pa_threaded_mainloop_unlock(pa->mainloop); pa_threaded_mainloop_unlock(pa->mainloop);
return length; return length;
} }

View File

@ -14,13 +14,13 @@
*/ */
#include "driver.h" #include "../../driver.h"
#include <stdlib.h> #include <stdlib.h>
#include <roaraudio.h> #include <roaraudio.h>
#include <errno.h> #include <errno.h>
#include <stdint.h> #include <stdint.h>
#include <boolean.h> #include <boolean.h>
#include "general.h" #include "../../general.h"
typedef struct typedef struct
{ {
@ -30,13 +30,15 @@ typedef struct
static void *ra_init(const char *device, unsigned rate, unsigned latency) static void *ra_init(const char *device, unsigned rate, unsigned latency)
{ {
(void)latency;
int err; int err;
roar_vs_t *vss;
roar_t *roar = (roar_t*)calloc(1, sizeof(roar_t)); roar_t *roar = (roar_t*)calloc(1, sizeof(roar_t));
if (roar == NULL)
if (!roar)
return NULL; return NULL;
roar_vs_t *vss; (void)latency;
if ((vss = roar_vs_new_simple(device, "RetroArch", rate, 2, ROAR_CODEC_PCM_S, 16, ROAR_DIR_PLAY, &err)) == NULL) if ((vss = roar_vs_new_simple(device, "RetroArch", rate, 2, ROAR_CODEC_PCM_S, 16, ROAR_DIR_PLAY, &err)) == NULL)
{ {
RARCH_ERR("RoarAudio: \"%s\"\n", roar_vs_strerr(err)); RARCH_ERR("RoarAudio: \"%s\"\n", roar_vs_strerr(err));
@ -52,17 +54,18 @@ static void *ra_init(const char *device, unsigned rate, unsigned latency)
static ssize_t ra_write(void *data, const void *buf, size_t size) static ssize_t ra_write(void *data, const void *buf, size_t size)
{ {
roar_t *roar = (roar_t*)data; int err;
ssize_t rc; ssize_t rc;
size_t written = 0;
roar_t *roar = (roar_t*)data;
if (size == 0) if (size == 0)
return 0; return 0;
int err;
size_t written = 0;
while (written < size) while (written < size)
{ {
size_t write_amt = size - written; size_t write_amt = size - written;
if ((rc = roar_vs_write(roar->vss, (const char*)buf + written, write_amt, &err)) < (ssize_t)write_amt) if ((rc = roar_vs_write(roar->vss, (const char*)buf + written, write_amt, &err)) < (ssize_t)write_amt)
{ {
if (roar->nonblocking) if (roar->nonblocking)
@ -87,9 +90,9 @@ static bool ra_stop(void *data)
static bool ra_alive(void *data) static bool ra_alive(void *data)
{ {
roar_t *roar = (roar_t*)data; roar_t *roar = (roar_t*)data;
if (roar) if (!roar)
return !roar->is_paused; return false;
return false; return !roar->is_paused;
} }
static void ra_set_nonblock_state(void *data, bool state) static void ra_set_nonblock_state(void *data, bool state)

View File

@ -13,10 +13,10 @@
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "../driver.h" #include "../../driver.h"
#include "../general.h" #include "../../general.h"
#include "../emscripten/RWebAudio.h" #include "../../emscripten/RWebAudio.h"
static bool rwebaudio_is_paused; static bool rwebaudio_is_paused;
@ -27,9 +27,11 @@ static void rwebaudio_free(void *data)
static void *rwebaudio_init(const char *device, unsigned rate, unsigned latency) static void *rwebaudio_init(const char *device, unsigned rate, unsigned latency)
{ {
void *data;
(void)device; (void)device;
(void)rate; (void)rate;
void *data = RWebAudioInit(latency); data = RWebAudioInit(latency);
if (data) if (data)
g_settings.audio.out_rate = RWebAudioSampleRate(); g_settings.audio.out_rate = RWebAudioSampleRate();
return data; return data;

View File

@ -14,7 +14,7 @@
*/ */
#include "../driver.h" #include "../../driver.h"
#include <stdlib.h> #include <stdlib.h>
#include <boolean.h> #include <boolean.h>
#include <stddef.h> #include <stddef.h>
@ -25,7 +25,7 @@
#include "SDL_audio.h" #include "SDL_audio.h"
#include <rthreads/rthreads.h> #include <rthreads/rthreads.h>
#include "../general.h" #include "../../general.h"
#include <queues/fifo_buffer.h> #include <queues/fifo_buffer.h>
typedef struct sdl_audio typedef struct sdl_audio
@ -41,26 +41,36 @@ typedef struct sdl_audio
static void sdl_audio_cb(void *data, Uint8 *stream, int len) static void sdl_audio_cb(void *data, Uint8 *stream, int len)
{ {
sdl_audio_t *sdl = (sdl_audio_t*)data; sdl_audio_t *sdl = (sdl_audio_t*)data;
size_t avail = fifo_read_avail(sdl->buffer); size_t avail = fifo_read_avail(sdl->buffer);
size_t write_size = len > (int)avail ? avail : len; size_t write_size = len > (int)avail ? avail : len;
fifo_read(sdl->buffer, stream, write_size); fifo_read(sdl->buffer, stream, write_size);
scond_signal(sdl->cond); scond_signal(sdl->cond);
// If underrun, fill rest with silence. /* If underrun, fill rest with silence. */
memset(stream + write_size, 0, len - write_size); memset(stream + write_size, 0, len - write_size);
} }
static inline int find_num_frames(int rate, int latency) static inline int find_num_frames(int rate, int latency)
{ {
int frames = (rate * latency) / 1000; int frames = (rate * latency) / 1000;
// SDL only likes 2^n sized buffers.
/* SDL only likes 2^n sized buffers. */
return next_pow2(frames); return next_pow2(frames);
} }
static void *sdl_audio_init(const char *device, unsigned rate, unsigned latency) static void *sdl_audio_init(const char *device,
unsigned rate, unsigned latency)
{ {
int frames;
size_t bufsize;
void *tmp;
SDL_AudioSpec out;
SDL_AudioSpec spec = {0};
sdl_audio_t *sdl = NULL;
(void)device; (void)device;
if (SDL_WasInit(0) == 0) if (SDL_WasInit(0) == 0)
{ {
if (SDL_Init(SDL_INIT_AUDIO) < 0) if (SDL_Init(SDL_INIT_AUDIO) < 0)
@ -69,14 +79,16 @@ static void *sdl_audio_init(const char *device, unsigned rate, unsigned latency)
else if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) else if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
return NULL; return NULL;
sdl_audio_t *sdl = (sdl_audio_t*)calloc(1, sizeof(*sdl)); sdl = (sdl_audio_t*)calloc(1, sizeof(*sdl));
if (!sdl) if (!sdl)
return NULL; return NULL;
// We have to buffer up some data ourselves, so we let SDL carry approx half of the latency. SDL double buffers audio and we do as well. /* We have to buffer up some data ourselves, so we let SDL
int frames = find_num_frames(rate, latency / 4); * carry approximately half of the latency.
*
* SDL double buffers audio and we do as well. */
frames = find_num_frames(rate, latency / 4);
SDL_AudioSpec spec = {0};
spec.freq = rate; spec.freq = rate;
spec.format = AUDIO_S16SYS; spec.format = AUDIO_S16SYS;
spec.channels = 2; spec.channels = 2;
@ -84,8 +96,6 @@ static void *sdl_audio_init(const char *device, unsigned rate, unsigned latency)
spec.callback = sdl_audio_cb; spec.callback = sdl_audio_cb;
spec.userdata = sdl; spec.userdata = sdl;
SDL_AudioSpec out;
if (SDL_OpenAudio(&spec, &out) < 0) if (SDL_OpenAudio(&spec, &out) < 0)
{ {
RARCH_ERR("Failed to open SDL audio: %s\n", SDL_GetError()); RARCH_ERR("Failed to open SDL audio: %s\n", SDL_GetError());
@ -97,12 +107,14 @@ static void *sdl_audio_init(const char *device, unsigned rate, unsigned latency)
sdl->lock = slock_new(); sdl->lock = slock_new();
sdl->cond = scond_new(); sdl->cond = scond_new();
RARCH_LOG("SDL audio: Requested %u ms latency, got %d ms\n", latency, (int)(out.samples * 4 * 1000 / g_settings.audio.out_rate)); RARCH_LOG("SDL audio: Requested %u ms latency, got %d ms\n",
latency, (int)(out.samples * 4 * 1000 / g_settings.audio.out_rate));
// Create a buffer twice as big as needed and prefill the buffer. /* Create a buffer twice as big as needed and prefill the buffer. */
size_t bufsize = out.samples * 4 * sizeof(int16_t); bufsize = out.samples * 4 * sizeof(int16_t);
void *tmp = calloc(1, bufsize); tmp = calloc(1, bufsize);
sdl->buffer = fifo_new(bufsize); sdl->buffer = fifo_new(bufsize);
if (tmp) if (tmp)
{ {
fifo_write(sdl->buffer, tmp, bufsize); fifo_write(sdl->buffer, tmp, bufsize);
@ -115,14 +127,16 @@ static void *sdl_audio_init(const char *device, unsigned rate, unsigned latency)
static ssize_t sdl_audio_write(void *data, const void *buf, size_t size) static ssize_t sdl_audio_write(void *data, const void *buf, size_t size)
{ {
ssize_t ret = 0;
sdl_audio_t *sdl = (sdl_audio_t*)data; sdl_audio_t *sdl = (sdl_audio_t*)data;
ssize_t ret = 0;
if (sdl->nonblock) if (sdl->nonblock)
{ {
size_t avail, write_amt;
SDL_LockAudio(); SDL_LockAudio();
size_t avail = fifo_write_avail(sdl->buffer); avail = fifo_write_avail(sdl->buffer);
size_t write_amt = avail > size ? size : avail; write_amt = avail > size ? size : avail;
fifo_write(sdl->buffer, buf, write_amt); fifo_write(sdl->buffer, buf, write_amt);
SDL_UnlockAudio(); SDL_UnlockAudio();
ret = write_amt; ret = write_amt;
@ -130,10 +144,13 @@ static ssize_t sdl_audio_write(void *data, const void *buf, size_t size)
else else
{ {
size_t written = 0; size_t written = 0;
while (written < size) while (written < size)
{ {
size_t avail;
SDL_LockAudio(); SDL_LockAudio();
size_t avail = fifo_write_avail(sdl->buffer); avail = fifo_write_avail(sdl->buffer);
if (avail == 0) if (avail == 0)
{ {
@ -167,9 +184,9 @@ static bool sdl_audio_stop(void *data)
static bool sdl_audio_alive(void *data) static bool sdl_audio_alive(void *data)
{ {
sdl_audio_t *sdl = (sdl_audio_t*)data; sdl_audio_t *sdl = (sdl_audio_t*)data;
if (sdl) if (!sdl)
return !sdl->is_paused; return false;
return false; return !sdl->is_paused;
} }
static bool sdl_audio_start(void *data) static bool sdl_audio_start(void *data)
@ -184,15 +201,17 @@ static bool sdl_audio_start(void *data)
static void sdl_audio_set_nonblock_state(void *data, bool state) static void sdl_audio_set_nonblock_state(void *data, bool state)
{ {
sdl_audio_t *sdl = (sdl_audio_t*)data; sdl_audio_t *sdl = (sdl_audio_t*)data;
sdl->nonblock = state; if (sdl)
sdl->nonblock = state;
} }
static void sdl_audio_free(void *data) static void sdl_audio_free(void *data)
{ {
sdl_audio_t *sdl = (sdl_audio_t*)data;
SDL_CloseAudio(); SDL_CloseAudio();
SDL_QuitSubSystem(SDL_INIT_AUDIO); SDL_QuitSubSystem(SDL_INIT_AUDIO);
sdl_audio_t *sdl = (sdl_audio_t*)data;
if (sdl) if (sdl)
{ {
fifo_free(sdl->buffer); fifo_free(sdl->buffer);

View File

@ -14,10 +14,10 @@
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "../driver.h" #include "../../driver.h"
#include <stdlib.h> #include <stdlib.h>
#include "xaudio-c/xaudio-c.h" #include "../xaudio-c/xaudio-c.h"
#include "../general.h" #include "../../general.h"
typedef struct typedef struct
{ {
@ -29,21 +29,24 @@ typedef struct
static void *xa_init(const char *device, unsigned rate, unsigned latency) static void *xa_init(const char *device, unsigned rate, unsigned latency)
{ {
size_t bufsize;
xa_t *xa;
unsigned device_index = 0;
if (latency < 8) if (latency < 8)
latency = 8; // Do not allow shenanigans. latency = 8; /* Do not allow shenanigans. */
xa_t *xa = (xa_t*)calloc(1, sizeof(*xa)); xa_t *xa = (xa_t*)calloc(1, sizeof(*xa));
if (!xa) if (!xa)
return NULL; return NULL;
size_t bufsize = latency * rate / 1000; bufsize = latency * rate / 1000;
RARCH_LOG("XAudio2: Requesting %u ms latency, using %d ms latency.\n", RARCH_LOG("XAudio2: Requesting %u ms latency, using %d ms latency.\n",
latency, (int)bufsize * 1000 / rate); latency, (int)bufsize * 1000 / rate);
xa->bufsize = bufsize * 2 * sizeof(float); xa->bufsize = bufsize * 2 * sizeof(float);
unsigned device_index = 0;
if (device) if (device)
device_index = strtoul(device, NULL, 0); device_index = strtoul(device, NULL, 0);
@ -63,17 +66,20 @@ static void *xa_init(const char *device, unsigned rate, unsigned latency)
static ssize_t xa_write(void *data, const void *buf, size_t size) static ssize_t xa_write(void *data, const void *buf, size_t size)
{ {
size_t ret;
xa_t *xa = (xa_t*)data; xa_t *xa = (xa_t*)data;
if (xa->nonblock) if (xa->nonblock)
{ {
size_t avail = xaudio2_write_avail(xa->xa); size_t avail = xaudio2_write_avail(xa->xa);
if (avail == 0) if (avail == 0)
return 0; return 0;
if (avail < size) if (avail < size)
size = avail; size = avail;
} }
size_t ret = xaudio2_write(xa->xa, buf, size); ret = xaudio2_write(xa->xa, buf, size);
if (ret == 0 && size > 0) if (ret == 0 && size > 0)
return -1; return -1;
return ret; return ret;
@ -89,15 +95,16 @@ static bool xa_stop(void *data)
static bool xa_alive(void *data) static bool xa_alive(void *data)
{ {
xa_t *xa = (xa_t*)data; xa_t *xa = (xa_t*)data;
if (xa) if (!xa)
return !xa->is_paused; return false;
return false; return !xa->is_paused;
} }
static void xa_set_nonblock_state(void *data, bool state) static void xa_set_nonblock_state(void *data, bool state)
{ {
xa_t *xa = (xa_t*)data; xa_t *xa = (xa_t*)data;
xa->nonblock = state; if (xa)
xa->nonblock = state;
} }
static bool xa_start(void *data) static bool xa_start(void *data)
@ -116,12 +123,13 @@ static bool xa_use_float(void *data)
static void xa_free(void *data) static void xa_free(void *data)
{ {
xa_t *xa = (xa_t*)data; xa_t *xa = (xa_t*)data;
if (xa)
{ if (!xa)
if (xa->xa) return;
xaudio2_free(xa->xa);
free(xa); if (xa->xa)
} xaudio2_free(xa->xa);
free(xa);
} }
static size_t xa_write_avail(void *data) static size_t xa_write_avail(void *data)

View File

@ -14,10 +14,10 @@
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "../driver.h" #include "../../driver.h"
#include <stdlib.h> #include <stdlib.h>
#include <boolean.h> #include <boolean.h>
#include "../general.h" #include "../../general.h"
#include <xenon_sound/sound.h> #include <xenon_sound/sound.h>
@ -35,6 +35,7 @@ static void *xenon360_audio_init(const char *device,
unsigned rate, unsigned latency) unsigned rate, unsigned latency)
{ {
static bool inited = false; static bool inited = false;
if (!inited) if (!inited)
{ {
xenon_sound_init(); xenon_sound_init();
@ -53,12 +54,11 @@ static inline uint32_t bswap_32(uint32_t val)
static ssize_t xenon360_audio_write(void *data, const void *buf, size_t size) static ssize_t xenon360_audio_write(void *data, const void *buf, size_t size)
{ {
size_t written = 0, i;
const uint32_t *in_buf = buf;
xenon_audio_t *xa = data; xenon_audio_t *xa = data;
size_t written = 0; for (i = 0; i < (size >> 2); i++)
const uint32_t *in_buf = buf;
for (size_t i = 0; i < (size >> 2); i++)
xa->buffer[i] = bswap_32(in_buf[i]); xa->buffer[i] = bswap_32(in_buf[i]);
if (!xa->nonblock) if (!xa->nonblock)
@ -95,15 +95,16 @@ static bool xenon360_audio_stop(void *data)
static bool xenon360_audio_alive(void *data) static bool xenon360_audio_alive(void *data)
{ {
xenon_audio_t *xa = data; xenon_audio_t *xa = data;
if (xa) if (!xa)
return !xa->is_paused; return false;
return false; return !xa->is_paused;
} }
static void xenon360_audio_set_nonblock_state(void *data, bool state) static void xenon360_audio_set_nonblock_state(void *data, bool state)
{ {
xenon_audio_t *xa = data; xenon_audio_t *xa = data;
xa->nonblock = state; if (xa)
xa->nonblock = state;
} }
static bool xenon360_audio_start(void *data) static bool xenon360_audio_start(void *data)

View File

@ -57,11 +57,13 @@ void x11_show_mouse(Display *dpy, Window win, bool state)
static Atom XA_NET_WM_STATE; static Atom XA_NET_WM_STATE;
static Atom XA_NET_WM_STATE_FULLSCREEN; static Atom XA_NET_WM_STATE_FULLSCREEN;
static Atom XA_NET_MOVERESIZE_WINDOW; static Atom XA_NET_MOVERESIZE_WINDOW;
#define XA_INIT(x) XA##x = XInternAtom(dpy, #x, False) #define XA_INIT(x) XA##x = XInternAtom(dpy, #x, False)
#define _NET_WM_STATE_ADD 1 #define _NET_WM_STATE_ADD 1
#define MOVERESIZE_GRAVITY_CENTER 5 #define MOVERESIZE_GRAVITY_CENTER 5
#define MOVERESIZE_X_SHIFT 8 #define MOVERESIZE_X_SHIFT 8
#define MOVERESIZE_Y_SHIFT 9 #define MOVERESIZE_Y_SHIFT 9
void x11_windowed_fullscreen(Display *dpy, Window win) void x11_windowed_fullscreen(Display *dpy, Window win)
{ {
XA_INIT(_NET_WM_STATE); XA_INIT(_NET_WM_STATE);
@ -82,7 +84,8 @@ void x11_windowed_fullscreen(Display *dpy, Window win)
&xev); &xev);
} }
// Try to be nice to tiling WMs if possible. /* Try to be nice to tiling WMs if possible. */
void x11_move_window(Display *dpy, Window win, int x, int y, void x11_move_window(Display *dpy, Window win, int x, int y,
unsigned width, unsigned height) unsigned width, unsigned height)
{ {
@ -108,7 +111,7 @@ static void x11_set_window_class(Display *dpy, Window win)
{ {
XClassHint hint = {0}; XClassHint hint = {0};
hint.res_name = (char*)"retroarch"; // Broken header. hint.res_name = (char*)"retroarch"; /* Broken header. */
hint.res_class = (char*)"retroarch"; hint.res_class = (char*)"retroarch";
XSetClassHint(dpy, win, &hint); XSetClassHint(dpy, win, &hint);
} }
@ -266,10 +269,12 @@ unsigned x11_get_xinerama_monitor(Display *dpy, int x, int y,
int len_x = min_rx - max_lx; int len_x = min_rx - max_lx;
int len_y = min_by - max_ty; int len_y = min_by - max_ty;
if (len_x < 0 || len_y < 0) // The whole window is outside the screen.
if (len_x < 0 || len_y < 0) /* The whole window is outside the screen. */
continue; continue;
area = len_x * len_y; area = len_x * len_y;
if (area > largest_area) if (area > largest_area)
{ {
monitor = i; monitor = i;
@ -285,6 +290,7 @@ unsigned x11_get_xinerama_monitor(Display *dpy, int x, int y,
bool x11_create_input_context(Display *dpy, Window win, XIM *xim, XIC *xic) bool x11_create_input_context(Display *dpy, Window win, XIM *xim, XIC *xic)
{ {
*xim = XOpenIM(dpy, NULL, NULL, NULL); *xim = XOpenIM(dpy, NULL, NULL, NULL);
if (!*xim) if (!*xim)
{ {
RARCH_ERR("[X11]: Failed to open input method.\n"); RARCH_ERR("[X11]: Failed to open input method.\n");
@ -293,6 +299,7 @@ bool x11_create_input_context(Display *dpy, Window win, XIM *xim, XIC *xic)
*xic = XCreateIC(*xim, XNInputStyle, *xic = XCreateIC(*xim, XNInputStyle,
XIMPreeditNothing | XIMStatusNothing, XNClientWindow, win, NULL); XIMPreeditNothing | XIMStatusNothing, XNClientWindow, win, NULL);
if (!*xic) if (!*xic)
{ {
RARCH_ERR("[X11]: Failed to create input context.\n"); RARCH_ERR("[X11]: Failed to create input context.\n");

View File

@ -451,48 +451,48 @@ RSOUND
AUDIO AUDIO
============================================================ */ ============================================================ */
#if defined(__CELLOS_LV2__) #if defined(__CELLOS_LV2__)
#include "../audio/ps3_audio.c" #include "../audio/drivers/ps3_audio.c"
#elif defined(XENON) #elif defined(XENON)
#include "../audio/xenon360_audio.c" #include "../audio/drivers/xenon360_audio.c"
#elif defined(GEKKO) #elif defined(GEKKO)
#include "../audio/gx_audio.c" #include "../audio/drivers/gx_audio.c"
#elif defined(EMSCRIPTEN) #elif defined(EMSCRIPTEN)
#include "../audio/rwebaudio.c" #include "../audio/drivers/rwebaudio.c"
#elif defined(PSP) #elif defined(PSP)
#include "../audio/psp1_audio.c" #include "../audio/drivers/psp1_audio.c"
#endif #endif
#ifdef HAVE_XAUDIO #ifdef HAVE_XAUDIO
#include "../audio/xaudio.c" #include "../audio/drivers/xaudio.c"
#include "../audio/xaudio-c/xaudio-c.cpp" #include "../audio/xaudio-c/xaudio-c.cpp"
#endif #endif
#ifdef HAVE_DSOUND #ifdef HAVE_DSOUND
#include "../audio/dsound.c" #include "../audio/drivers/dsound.c"
#endif #endif
#ifdef HAVE_SL #ifdef HAVE_SL
#include "../audio/opensl.c" #include "../audio/drivers/opensl.c"
#endif #endif
#ifdef HAVE_ALSA #ifdef HAVE_ALSA
#ifdef __QNX__ #ifdef __QNX__
#include "../audio/alsa_qsa.c" #include "../audio/drivers/alsa_qsa.c"
#else #else
#include "../audio/alsa.c" #include "../audio/drivers/alsa.c"
#include "../audio/alsathread.c" #include "../audio/drivers/alsathread.c"
#endif #endif
#endif #endif
#ifdef HAVE_AL #ifdef HAVE_AL
#include "../audio/openal.c" #include "../audio/drivers/openal.c"
#endif #endif
#ifdef HAVE_COREAUDIO #ifdef HAVE_COREAUDIO
#include "../audio/coreaudio.c" #include "../audio/drivers/coreaudio.c"
#endif #endif
#include "../audio/nullaudio.c" #include "../audio/drivers/nullaudio.c"
/*============================================================ /*============================================================
DRIVERS DRIVERS