mirror of
https://github.com/libretro/RetroArch
synced 2025-03-20 10:20:51 +00:00
MOve audio drivers to audio/drivers
This commit is contained in:
parent
5f611f7270
commit
1753430d68
@ -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
|
||||
|
@ -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; \
|
@ -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
|
@ -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)
|
@ -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;
|
||||
}
|
||||
|
@ -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, ®ion->chunk1, ®ion->size1, ®ion->chunk2, ®ion->size2, 0);
|
||||
const char *err;
|
||||
HRESULT res = IDirectSoundBuffer_Lock(ds->dsb, write_ptr, CHUNK_SIZE,
|
||||
®ion->chunk1, ®ion->size1, ®ion->chunk2, ®ion->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, ®ion->chunk1, ®ion->size1, ®ion->chunk2, ®ion->size2, 0);
|
||||
res = IDirectSoundBuffer_Lock(ds->dsb, write_ptr, CHUNK_SIZE,
|
||||
®ion->chunk1, ®ion->size1, ®ion->chunk2, ®ion->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, ®ion))
|
||||
{
|
||||
ds->thread_alive = false;
|
||||
@ -184,9 +197,10 @@ static DWORD CALLBACK dsound_thread(PVOID data)
|
||||
release_region(ds, ®ion);
|
||||
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, ®ion))
|
||||
{
|
||||
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;
|
||||
}
|
@ -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)
|
@ -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)
|
@ -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)
|
||||
{
|
@ -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)
|
@ -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);
|
@ -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
|
@ -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)
|
@ -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)
|
@ -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;
|
||||
}
|
@ -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)
|
@ -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;
|
@ -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);
|
@ -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)
|
@ -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)
|
@ -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");
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user