1
0
mirror of https://github.com/libretro/RetroArch synced 2024-07-03 00:38:44 +00:00

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

View File

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

View File

@ -14,8 +14,8 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "../general.h"
#include "../driver.h"
#include "../../general.h"
#include "../../driver.h"
#define ALSA_PCM_NEW_HW_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 <alsa/asoundlib.h>
#include "../general.h"
#include "../../general.h"
#include <rthreads/rthreads.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)
{
alsa_thread_t *alsa = (alsa_thread_t*)data;
if (alsa)
return !alsa->is_paused;
return false;
if (!alsa)
return false;
return !alsa->is_paused;
}
static bool alsa_thread_stop(void *data)

View File

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

View File

@ -39,7 +39,7 @@ static DSMIXBINVOLUMEPAIR dsmbvp[8] = {
static DSMIXBINS dsmb;
#endif
#include "../driver.h"
#include "../../driver.h"
#include <stdlib.h>
#include <boolean.h>
#include <stddef.h>
@ -53,7 +53,7 @@ static DSMIXBINS dsmb;
#endif
#include <dsound.h>
#include <queues/fifo_buffer.h>
#include "../general.h"
#include "../../general.h"
typedef struct dsound
{
@ -93,21 +93,25 @@ struct audio_lock
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)
{
res = IDirectSoundBuffer_Restore(ds->dsb);
if (res != DS_OK)
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)
return false;
}
const char *err;
switch (res)
{
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)
{
DWORD write_ptr;
dsound_t *ds = (dsound_t*)data;
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
DWORD write_ptr;
get_positions(ds, NULL, &write_ptr);
write_ptr = (write_ptr + ds->buffer_size / 2) % ds->buffer_size;
while (ds->thread_alive)
{
DWORD read_ptr;
struct audio_lock region;
DWORD read_ptr, avail, fifo_avail;
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);
DWORD fifo_avail = fifo_read_avail(ds->buffer);
fifo_avail = fifo_read_avail(ds->buffer);
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)))
{
/* No space to write, or we don't have data in our fifo,
* but we can wait some time before it underruns ... */
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))
{
ds->thread_alive = false;
@ -184,9 +197,10 @@ static DWORD CALLBACK dsound_thread(PVOID data)
release_region(ds, &region);
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))
{
ds->thread_alive = false;
@ -213,13 +227,13 @@ static DWORD CALLBACK dsound_thread(PVOID data)
static void dsound_stop_thread(dsound_t *ds)
{
if (ds->thread)
{
ds->thread_alive = false;
WaitForSingleObject(ds->thread, INFINITE);
CloseHandle(ds->thread);
ds->thread = NULL;
}
if (!ds->thread)
return;
ds->thread_alive = false;
WaitForSingleObject(ds->thread, INFINITE);
CloseHandle(ds->thread);
ds->thread = NULL;
}
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)
{
IDirectSoundBuffer_SetCurrentPosition(ds->dsb, 0);
void *ptr;
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);
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)
{
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);
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);
ds->thread_alive = false;
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);
}
struct dsound_dev
@ -291,7 +307,9 @@ struct dsound_dev
static BOOL CALLBACK enumerate_cb(LPGUID guid, LPCSTR desc, LPCSTR module, LPVOID context)
{
struct dsound_dev *dev = (struct dsound_dev*)context;
RARCH_LOG("\t%u: %s\n", dev->total_count, desc);
if (dev->device == dev->total_count)
dev->guid = guid;
dev->total_count++;
@ -303,8 +321,8 @@ static void *dsound_init(const char *device, unsigned rate, unsigned latency)
WAVEFORMATEX wfx = {0};
DSBUFFERDESC bufdesc = {0};
struct dsound_dev dev = {0};
dsound_t *ds = (dsound_t*)calloc(1, sizeof(*ds));
if (!ds)
goto error;
@ -384,14 +402,17 @@ error:
static bool dsound_stop(void *data)
{
dsound_t *ds = (dsound_t*)data;
dsound_stop_thread(ds);
ds->is_paused = (IDirectSoundBuffer_Stop(ds->dsb) == DS_OK) ? true : false;
return (ds->is_paused) ? true : false;
}
static bool dsound_start(void *data)
{
dsound_t *ds = (dsound_t*)data;
dsound_clear_buffer(ds);
if (!dsound_start_thread(ds))
@ -404,30 +425,34 @@ static bool dsound_start(void *data)
static bool dsound_alive(void *data)
{
dsound_t *ds = (dsound_t*)data;
if (ds)
return !ds->is_paused;
return false;
if (!ds)
return false;
return !ds->is_paused;
}
static void dsound_set_nonblock_state(void *data, bool state)
{
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)
{
size_t written = 0;
dsound_t *ds = (dsound_t*)data;
const uint8_t *buf = (const uint8_t*)buf_;
if (!ds->thread_alive)
return -1;
size_t written = 0;
while (size > 0)
{
size_t avail;
EnterCriticalSection(&ds->crit);
size_t avail = fifo_write_avail(ds->buffer);
avail = fifo_write_avail(ds->buffer);
if (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)
{
size_t avail;
dsound_t *ds = (dsound_t*)data;
EnterCriticalSection(&ds->crit);
size_t avail = fifo_write_avail(ds->buffer);
avail = fifo_write_avail(ds->buffer);
LeaveCriticalSection(&ds->crit);
return avail;
}

View File

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

View File

@ -14,9 +14,9 @@
*/
#include "../driver.h"
#include "../../driver.h"
#include <stdlib.h>
#include "../general.h"
#include "../../general.h"
#include <jack/jack.h>
#include <jack/types.h>
@ -46,18 +46,18 @@ typedef struct jack
static int process_cb(jack_nframes_t nframes, void *data)
{
int i;
jack_nframes_t f;
jack_nframes_t f, avail[2], min_avail;
jack_t *jd = (jack_t*)data;
if (nframes <= 0)
{
pthread_cond_signal(&jd->cond);
return 0;
}
jack_nframes_t avail[2];
avail[0] = jack_ringbuffer_read_space(jd->buffer[0]);
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)
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));
for (f = min_avail; f < nframes; f++)
{
out[f] = 0.0f;
}
}
pthread_cond_signal(&jd->cond);
return 0;
@ -80,6 +78,10 @@ static int process_cb(jack_nframes_t nframes, void *data)
static void shutdown_cb(void *data)
{
jack_t *jd = (jack_t*)data;
if (!jd)
return;
jd->shutdown = true;
pthread_cond_signal(&jd->cond);
}
@ -88,8 +90,8 @@ static int parse_ports(char **dest_ports, const char **jports)
{
int i;
char *save;
const char *con = strtok_r(g_settings.audio.device, ",", &save);
int parsed = 0;
const char *con = strtok_r(g_settings.audio.device, ",", &save);
if (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)
{
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;
jack_latency_range_t range;
int jack_latency = 0;
for (i = 0; i < 2; i++)
{
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);
int buffer_frames = frames - jack_latency;
int min_buffer_frames = jack_get_buffer_size(jd->client) * 2;
buffer_frames = frames - jack_latency;
min_buffer_frames = jack_get_buffer_size(jd->client) * 2;
RARCH_LOG("JACK: Minimum buffer size is %d frames.\n", 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)
{
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));
if (!jd)
return NULL;
pthread_cond_init(&jd->cond, 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);
if (jd->client == NULL)
@ -214,12 +216,12 @@ error:
static size_t write_buffer(jack_t *jd, const float *buf, size_t size)
{
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];
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)
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++)
out_deinterleaved_buffer[i][j] = buf[j * 2 + i];
size_t written = 0;
while (written < frames)
{
size_t avail[2], min_avail, write_frames;
if (jd->shutdown)
return 0;
size_t avail[2] = {
jack_ringbuffer_write_space(jd->buffer[0]),
jack_ringbuffer_write_space(jd->buffer[1]),
};
avail[0] = jack_ringbuffer_write_space(jd->buffer[0]);
avail[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);
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)
{
@ -284,15 +284,16 @@ static bool ja_stop(void *data)
static bool ja_alive(void *data)
{
jack_t *jd = (jack_t*)data;
if (jd)
return !jd->is_paused;
return false;
if (!jd)
return false;
return !jd->is_paused;
}
static void ja_set_nonblock_state(void *data, bool state)
{
jack_t *jd = (jack_t*)data;
jd->nonblock = state;
if (jd)
jd->nonblock = state;
}
static bool ja_start(void *data)

View File

@ -13,8 +13,8 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "../general.h"
#include "../driver.h"
#include "../../general.h"
#include "../../driver.h"
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/>.
*/
#include "../driver.h"
#include "../general.h"
#include "../../driver.h"
#include "../../general.h"
#ifdef __APPLE__
#include <OpenAL/al.h>
@ -56,6 +56,7 @@ typedef struct al
static void al_free(void *data)
{
al_t *al = (al_t*)data;
if (!al)
return;
@ -78,24 +79,27 @@ static void al_free(void *data)
static void *al_init(const char *device, unsigned rate, unsigned latency)
{
al_t *al;
(void)device;
al_t *al = (al_t*)calloc(1, sizeof(al_t));
al = (al_t*)calloc(1, sizeof(al_t));
if (!al)
return NULL;
al->handle = alcOpenDevice(NULL);
if (al->handle == NULL)
if (!al->handle)
goto error;
al->ctx = alcCreateContext(al->handle, NULL);
if (al->ctx == NULL)
if (!al->ctx)
goto error;
alcMakeContextCurrent(al->ctx);
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;
if (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);
if (val > 0)
{
alSourceUnqueueBuffers(al->source, val, &al->res_buf[al->res_ptr]);
al->res_ptr += val;
return true;
}
if (val <= 0)
return false;
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)
@ -169,11 +171,14 @@ static ssize_t al_write(void *data, const void *buf_, size_t size)
{
al_t *al = (al_t*)data;
const uint8_t *buf = (const uint8_t*)buf_;
size_t written = 0;
while (size)
{
ALint val;
ALuint buffer;
size_t rc = al_fill_internal_buf(al, buf, size);
written += rc;
buf += 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)
break;
ALuint buffer;
if (!al_get_buffer(al, &buffer))
break;
@ -191,7 +195,6 @@ static ssize_t al_write(void *data, const void *buf_, size_t size)
if (alGetError() != AL_NO_ERROR)
return -1;
ALint val;
alGetSourcei(al->source, AL_SOURCE_STATE, &val);
if (val != AL_PLAYING)
alSourcePlay(al->source);
@ -214,15 +217,16 @@ static bool al_stop(void *data)
static bool al_alive(void *data)
{
al_t *al = (al_t*)data;
if (al)
return !al->is_paused;
return false;
if (!al)
return false;
return !al->is_paused;
}
static void al_set_nonblock_state(void *data, bool state)
{
al_t *al = (al_t*)data;
al->nonblock = state;
if (al)
al->nonblock = state;
}
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)
{
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)

View File

@ -14,8 +14,8 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "../driver.h"
#include "../general.h"
#include "../../driver.h"
#include "../../general.h"
#include <rthreads/rthreads.h>
#include <SLES/OpenSLES.h>
@ -23,7 +23,7 @@
#include <SLES/OpenSLES_Android.h>
#endif
// Helper macros, COM-style!
/* Helper macros, COM-style. */
#define SLObjectItf_Realize(a, ...) ((*(a))->Realize(a, __VA_ARGS__))
#define SLObjectItf_GetInterface(a, ...) ((*(a))->GetInterface(a, __VA_ARGS__))
#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)
{
unsigned i;
(void)device;
SLInterfaceID id;
SLboolean req;
SLresult res;
sl_t *sl;
SLDataFormat_PCM fmt_pcm = {0};
SLDataSource audio_src = {0};
SLDataSink audio_sink = {0};
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {0};
SLDataLocator_OutputMix loc_outmix = {0};
SLInterfaceID id = SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
SLboolean req = SL_BOOLEAN_TRUE;
(void)device;
SLresult res = 0;
sl_t *sl = (sl_t*)calloc(1, sizeof(sl_t));
id = SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
req = SL_BOOLEAN_TRUE;
res = 0;
sl = (sl_t*)calloc(1, sizeof(sl_t));
if (!sl)
goto error;
@ -154,7 +157,7 @@ static void *sl_init(const char *device, unsigned rate, unsigned latency)
fmt_pcm.bitsPerSample = 16;
fmt_pcm.containerSize = 16;
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.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);
// Enqueue a bit to get stuff rolling.
/* Enqueue a bit to get stuff rolling. */
sl->buffered_blocks = sl->buf_count;
sl->buffer_index = 0;
for (i = 0; i < sl->buf_count; i++)
@ -207,15 +210,16 @@ static bool sl_stop(void *data)
static bool sl_alive(void *data)
{
sl_t *sl = (sl_t*)data;
if (sl)
return !sl->is_paused;
return false;
if (!sl)
return false;
return !sl->is_paused;
}
static void sl_set_nonblock_state(void *data, bool state)
{
sl_t *sl = (sl_t*)data;
sl->nonblock = state;
if (sl)
sl->nonblock = state;
}
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)
{
sl_t *sl = (sl_t*)data;
size_t written = 0;
const uint8_t *buf = (const uint8_t*)buf_;
while (size)
{
size_t avail_write;
if (sl->nonblock)
{
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);
}
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)
{
memcpy(sl->buffer[sl->buffer_index] + sl->buffer_ptr, buf, avail_write);

View File

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

View File

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

View File

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

View File

@ -14,8 +14,8 @@
*/
#include "driver.h"
#include "general.h"
#include "../../driver.h"
#include "../../general.h"
#include <pulse/pulseaudio.h>
#include <boolean.h>
#include <string.h>
@ -35,28 +35,29 @@ typedef struct
static void pulse_free(void *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_threaded_mainloop_stop(pa->mainloop);
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);
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);
}
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)
{
pa_t *pa = (pa_t*)data;
switch (pa_context_get_state(c))
{
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)
{
pa_t *pa = (pa_t*)data;
switch (pa_stream_get_state(s))
{
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)
{
pa_t *pa = (pa_t*)data;
(void)length;
(void)s;
pa_t *pa = (pa_t*)data;
pa_threaded_mainloop_signal(pa->mainloop, 0);
}
static void stream_latency_update_cb(pa_stream *s, void *data)
{
(void)s;
pa_t *pa = (pa_t*)data;
(void)s;
pa_threaded_mainloop_signal(pa->mainloop, 0);
}
static void underrun_update_cb(pa_stream *s, void *data)
{
(void)s;
pa_t *pa = (pa_t*)data;
(void)s;
RARCH_LOG("[PulseAudio]: Underrun (Buffer: %u, Writable size: %u).\n",
(unsigned)pa->buffer_size,
(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)
{
const pa_buffer_attr *server_attr = NULL;
pa_sample_spec spec;
memset(&spec, 0, sizeof(spec));
pa_t *pa;
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)
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;
const uint8_t *buf = (const uint8_t*)buf_;
size_t written = 0;
pa_threaded_mainloop_lock(pa->mainloop);
while (size)
{
size_t writable = pa_stream_writable_size(pa->stream);
writable = min(size, 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)
{
RARCH_LOG("[PulseAudio]: Pausing.\n");
bool ret;
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_stream_cork(pa->stream, true, stream_success_cb, pa);
pa_threaded_mainloop_wait(pa->mainloop);
bool ret = pa->success;
ret = pa->success;
pa_threaded_mainloop_unlock(pa->mainloop);
pa->is_paused = true;
return ret;
@ -261,20 +276,24 @@ static bool pulse_stop(void *data)
static bool pulse_alive(void *data)
{
pa_t *pa = (pa_t*)data;
if (pa)
return !pa->is_paused;
return false;
if (!pa)
return false;
return !pa->is_paused;
}
static bool pulse_start(void *data)
{
RARCH_LOG("[PulseAudio]: Unpausing.\n");
bool ret;
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_stream_cork(pa->stream, false, stream_success_cb, pa);
pa_threaded_mainloop_wait(pa->mainloop);
bool ret = pa->success;
ret = pa->success;
pa_threaded_mainloop_unlock(pa->mainloop);
pa->is_paused = false;
return ret;
@ -283,7 +302,8 @@ static bool pulse_start(void *data)
static void pulse_set_nonblock_state(void *data, bool state)
{
pa_t *pa = (pa_t*)data;
pa->nonblock = state;
if (pa)
pa->nonblock = state;
}
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)
{
size_t length;
pa_t *pa = (pa_t*)data;
pa_threaded_mainloop_lock(pa->mainloop);
size_t length = pa_stream_writable_size(pa->stream);
g_extern.audio_data.driver_buffer_size = pa->buffer_size; // Can change spuriously.
length = pa_stream_writable_size(pa->stream);
g_extern.audio_data.driver_buffer_size = pa->buffer_size; /* Can change spuriously. */
pa_threaded_mainloop_unlock(pa->mainloop);
return length;
}

View File

@ -14,13 +14,13 @@
*/
#include "driver.h"
#include "../../driver.h"
#include <stdlib.h>
#include <roaraudio.h>
#include <errno.h>
#include <stdint.h>
#include <boolean.h>
#include "general.h"
#include "../../general.h"
typedef struct
{
@ -30,13 +30,15 @@ typedef struct
static void *ra_init(const char *device, unsigned rate, unsigned latency)
{
(void)latency;
int err;
roar_vs_t *vss;
roar_t *roar = (roar_t*)calloc(1, sizeof(roar_t));
if (roar == NULL)
if (!roar)
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)
{
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)
{
roar_t *roar = (roar_t*)data;
int err;
ssize_t rc;
size_t written = 0;
roar_t *roar = (roar_t*)data;
if (size == 0)
return 0;
int err;
size_t written = 0;
while (written < size)
{
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 (roar->nonblocking)
@ -87,9 +90,9 @@ static bool ra_stop(void *data)
static bool ra_alive(void *data)
{
roar_t *roar = (roar_t*)data;
if (roar)
return !roar->is_paused;
return false;
if (!roar)
return false;
return !roar->is_paused;
}
static void ra_set_nonblock_state(void *data, bool state)

View File

@ -13,10 +13,10 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "../driver.h"
#include "../general.h"
#include "../../driver.h"
#include "../../general.h"
#include "../emscripten/RWebAudio.h"
#include "../../emscripten/RWebAudio.h"
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)
{
void *data;
(void)device;
(void)rate;
void *data = RWebAudioInit(latency);
data = RWebAudioInit(latency);
if (data)
g_settings.audio.out_rate = RWebAudioSampleRate();
return data;

View File

@ -14,7 +14,7 @@
*/
#include "../driver.h"
#include "../../driver.h"
#include <stdlib.h>
#include <boolean.h>
#include <stddef.h>
@ -25,7 +25,7 @@
#include "SDL_audio.h"
#include <rthreads/rthreads.h>
#include "../general.h"
#include "../../general.h"
#include <queues/fifo_buffer.h>
typedef struct sdl_audio
@ -41,26 +41,36 @@ typedef struct sdl_audio
static void sdl_audio_cb(void *data, Uint8 *stream, int len)
{
sdl_audio_t *sdl = (sdl_audio_t*)data;
size_t avail = fifo_read_avail(sdl->buffer);
size_t write_size = len > (int)avail ? avail : len;
fifo_read(sdl->buffer, stream, write_size);
scond_signal(sdl->cond);
// If underrun, fill rest with silence.
/* If underrun, fill rest with silence. */
memset(stream + write_size, 0, len - write_size);
}
static inline int find_num_frames(int rate, int latency)
{
int frames = (rate * latency) / 1000;
// SDL only likes 2^n sized buffers.
/* SDL only likes 2^n sized buffers. */
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;
if (SDL_WasInit(0) == 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)
return NULL;
sdl_audio_t *sdl = (sdl_audio_t*)calloc(1, sizeof(*sdl));
sdl = (sdl_audio_t*)calloc(1, sizeof(*sdl));
if (!sdl)
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.
int frames = find_num_frames(rate, latency / 4);
/* We have to buffer up some data ourselves, so we let SDL
* 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.format = AUDIO_S16SYS;
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.userdata = sdl;
SDL_AudioSpec out;
if (SDL_OpenAudio(&spec, &out) < 0)
{
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->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.
size_t bufsize = out.samples * 4 * sizeof(int16_t);
void *tmp = calloc(1, bufsize);
/* Create a buffer twice as big as needed and prefill the buffer. */
bufsize = out.samples * 4 * sizeof(int16_t);
tmp = calloc(1, bufsize);
sdl->buffer = fifo_new(bufsize);
if (tmp)
{
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)
{
ssize_t ret = 0;
sdl_audio_t *sdl = (sdl_audio_t*)data;
ssize_t ret = 0;
if (sdl->nonblock)
{
size_t avail, write_amt;
SDL_LockAudio();
size_t avail = fifo_write_avail(sdl->buffer);
size_t write_amt = avail > size ? size : avail;
avail = fifo_write_avail(sdl->buffer);
write_amt = avail > size ? size : avail;
fifo_write(sdl->buffer, buf, write_amt);
SDL_UnlockAudio();
ret = write_amt;
@ -130,10 +144,13 @@ static ssize_t sdl_audio_write(void *data, const void *buf, size_t size)
else
{
size_t written = 0;
while (written < size)
{
size_t avail;
SDL_LockAudio();
size_t avail = fifo_write_avail(sdl->buffer);
avail = fifo_write_avail(sdl->buffer);
if (avail == 0)
{
@ -167,9 +184,9 @@ static bool sdl_audio_stop(void *data)
static bool sdl_audio_alive(void *data)
{
sdl_audio_t *sdl = (sdl_audio_t*)data;
if (sdl)
return !sdl->is_paused;
return false;
if (!sdl)
return false;
return !sdl->is_paused;
}
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)
{
sdl_audio_t *sdl = (sdl_audio_t*)data;
sdl->nonblock = state;
if (sdl)
sdl->nonblock = state;
}
static void sdl_audio_free(void *data)
{
sdl_audio_t *sdl = (sdl_audio_t*)data;
SDL_CloseAudio();
SDL_QuitSubSystem(SDL_INIT_AUDIO);
sdl_audio_t *sdl = (sdl_audio_t*)data;
if (sdl)
{
fifo_free(sdl->buffer);

View File

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

View File

@ -14,10 +14,10 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "../driver.h"
#include "../../driver.h"
#include <stdlib.h>
#include <boolean.h>
#include "../general.h"
#include "../../general.h"
#include <xenon_sound/sound.h>
@ -35,6 +35,7 @@ static void *xenon360_audio_init(const char *device,
unsigned rate, unsigned latency)
{
static bool inited = false;
if (!inited)
{
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)
{
size_t written = 0, i;
const uint32_t *in_buf = buf;
xenon_audio_t *xa = data;
size_t written = 0;
const uint32_t *in_buf = buf;
for (size_t i = 0; i < (size >> 2); i++)
for (i = 0; i < (size >> 2); i++)
xa->buffer[i] = bswap_32(in_buf[i]);
if (!xa->nonblock)
@ -95,15 +95,16 @@ static bool xenon360_audio_stop(void *data)
static bool xenon360_audio_alive(void *data)
{
xenon_audio_t *xa = data;
if (xa)
return !xa->is_paused;
return false;
if (!xa)
return false;
return !xa->is_paused;
}
static void xenon360_audio_set_nonblock_state(void *data, bool state)
{
xenon_audio_t *xa = data;
xa->nonblock = state;
if (xa)
xa->nonblock = state;
}
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_FULLSCREEN;
static Atom XA_NET_MOVERESIZE_WINDOW;
#define XA_INIT(x) XA##x = XInternAtom(dpy, #x, False)
#define _NET_WM_STATE_ADD 1
#define MOVERESIZE_GRAVITY_CENTER 5
#define MOVERESIZE_X_SHIFT 8
#define MOVERESIZE_Y_SHIFT 9
void x11_windowed_fullscreen(Display *dpy, Window win)
{
XA_INIT(_NET_WM_STATE);
@ -82,7 +84,8 @@ void x11_windowed_fullscreen(Display *dpy, Window win)
&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,
unsigned width, unsigned height)
{
@ -108,7 +111,7 @@ static void x11_set_window_class(Display *dpy, Window win)
{
XClassHint hint = {0};
hint.res_name = (char*)"retroarch"; // Broken header.
hint.res_name = (char*)"retroarch"; /* Broken header. */
hint.res_class = (char*)"retroarch";
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_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;
area = len_x * len_y;
if (area > largest_area)
{
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)
{
*xim = XOpenIM(dpy, NULL, NULL, NULL);
if (!*xim)
{
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,
XIMPreeditNothing | XIMStatusNothing, XNClientWindow, win, NULL);
if (!*xic)
{
RARCH_ERR("[X11]: Failed to create input context.\n");

View File

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