diff --git a/Makefile.common b/Makefile.common
index f48484a7ae..fc4548ca24 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -97,6 +97,7 @@ OBJ += frontend/frontend.o \
file_ops.o \
libretro-sdk/file/file_path.o \
hash.o \
+ audio_driver.o \
driver.o \
settings.o \
settings_list.o \
diff --git a/audio_driver.c b/audio_driver.c
new file mode 100644
index 0000000000..30ef88cf48
--- /dev/null
+++ b/audio_driver.c
@@ -0,0 +1,383 @@
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ * Copyright (C) 2011-2015 - Daniel De Matteis
+ *
+ * RetroArch is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with RetroArch.
+ * If not, see .
+ */
+
+#include
+#include
+#include "audio_driver.h"
+#include "audio/utils.h"
+#include "audio/audio_thread_wrapper.h"
+#include "driver.h"
+#include "general.h"
+#include "retroarch.h"
+
+static const audio_driver_t *audio_drivers[] = {
+#ifdef HAVE_ALSA
+ &audio_alsa,
+#ifndef __QNX__
+ &audio_alsathread,
+#endif
+#endif
+#if defined(HAVE_OSS) || defined(HAVE_OSS_BSD)
+ &audio_oss,
+#endif
+#ifdef HAVE_RSOUND
+ &audio_rsound,
+#endif
+#ifdef HAVE_COREAUDIO
+ &audio_coreaudio,
+#endif
+#ifdef HAVE_AL
+ &audio_openal,
+#endif
+#ifdef HAVE_SL
+ &audio_opensl,
+#endif
+#ifdef HAVE_ROAR
+ &audio_roar,
+#endif
+#ifdef HAVE_JACK
+ &audio_jack,
+#endif
+#if defined(HAVE_SDL) || defined(HAVE_SDL2)
+ &audio_sdl,
+#endif
+#ifdef HAVE_XAUDIO
+ &audio_xa,
+#endif
+#ifdef HAVE_DSOUND
+ &audio_dsound,
+#endif
+#ifdef HAVE_PULSE
+ &audio_pulse,
+#endif
+#ifdef __CELLOS_LV2__
+ &audio_ps3,
+#endif
+#ifdef XENON
+ &audio_xenon360,
+#endif
+#ifdef GEKKO
+ &audio_gx,
+#endif
+#ifdef EMSCRIPTEN
+ &audio_rwebaudio,
+#endif
+#ifdef PSP
+ &audio_psp1,
+#endif
+ &audio_null,
+ NULL,
+};
+
+/**
+ * compute_audio_buffer_statistics:
+ *
+ * Computes audio buffer statistics.
+ *
+ **/
+static void compute_audio_buffer_statistics(void)
+{
+ unsigned i, low_water_size, high_water_size, avg, stddev;
+ float avg_filled, deviation;
+ uint64_t accum = 0, accum_var = 0;
+ unsigned low_water_count = 0, high_water_count = 0;
+ unsigned samples = min(g_extern.measure_data.buffer_free_samples_count,
+ AUDIO_BUFFER_FREE_SAMPLES_COUNT);
+
+ if (samples < 3)
+ return;
+
+ for (i = 1; i < samples; i++)
+ accum += g_extern.measure_data.buffer_free_samples[i];
+
+ avg = accum / (samples - 1);
+
+ for (i = 1; i < samples; i++)
+ {
+ int diff = avg - g_extern.measure_data.buffer_free_samples[i];
+ accum_var += diff * diff;
+ }
+
+ stddev = (unsigned)sqrt((double)accum_var / (samples - 2));
+ avg_filled = 1.0f - (float)avg / g_extern.audio_data.driver_buffer_size;
+ deviation = (float)stddev / g_extern.audio_data.driver_buffer_size;
+
+ low_water_size = g_extern.audio_data.driver_buffer_size * 3 / 4;
+ high_water_size = g_extern.audio_data.driver_buffer_size / 4;
+
+ for (i = 1; i < samples; i++)
+ {
+ if (g_extern.measure_data.buffer_free_samples[i] >= low_water_size)
+ low_water_count++;
+ else if (g_extern.measure_data.buffer_free_samples[i] <= high_water_size)
+ high_water_count++;
+ }
+
+ RARCH_LOG("Average audio buffer saturation: %.2f %%, standard deviation (percentage points): %.2f %%.\n",
+ avg_filled * 100.0, deviation * 100.0);
+ RARCH_LOG("Amount of time spent close to underrun: %.2f %%. Close to blocking: %.2f %%.\n",
+ (100.0 * low_water_count) / (samples - 1),
+ (100.0 * high_water_count) / (samples - 1));
+}
+
+/**
+ * audio_driver_find_handle:
+ * @index : index of driver to get handle to.
+ *
+ * Returns: handle to audio driver at index. Can be NULL
+ * if nothing found.
+ **/
+const void *audio_driver_find_handle(int index)
+{
+ const void *drv = audio_drivers[index];
+ if (!drv)
+ return NULL;
+ return drv;
+}
+
+/**
+ * audio_driver_find_ident:
+ * @index : index of driver to get handle to.
+ *
+ * Returns: Human-readable identifier of audio driver at index. Can be NULL
+ * if nothing found.
+ **/
+const char *audio_driver_find_ident(int index)
+{
+ const audio_driver_t *drv = audio_drivers[index];
+ if (!drv)
+ return NULL;
+ return drv->ident;
+}
+
+/**
+ * config_get_audio_driver_options:
+ *
+ * Get an enumerated list of all audio driver names, separated by '|'.
+ *
+ * Returns: string listing of all audio driver names, separated by '|'.
+ **/
+const char* config_get_audio_driver_options(void)
+{
+ union string_list_elem_attr attr;
+ unsigned i;
+ char *options = NULL;
+ int options_len = 0;
+ struct string_list *options_l = string_list_new();
+
+ attr.i = 0;
+
+ for (i = 0; audio_driver_find_handle(i); i++)
+ {
+ const char *opt = audio_driver_find_ident(i);
+ options_len += strlen(opt) + 1;
+ string_list_append(options_l, opt, attr);
+ }
+
+ options = (char*)calloc(options_len, sizeof(char));
+
+ string_list_join_concat(options, options_len, options_l, "|");
+
+ string_list_free(options_l);
+ options_l = NULL;
+
+ return options;
+}
+
+void find_audio_driver(void)
+{
+ int i = find_driver_index("audio_driver", g_settings.audio.driver);
+ if (i >= 0)
+ driver.audio = audio_driver_find_handle(i);
+ else
+ {
+ unsigned d;
+ RARCH_ERR("Couldn't find any audio driver named \"%s\"\n",
+ g_settings.audio.driver);
+ RARCH_LOG_OUTPUT("Available audio drivers are:\n");
+ for (d = 0; audio_driver_find_handle(d); d++)
+ RARCH_LOG_OUTPUT("\t%s\n", audio_driver_find_ident(d));
+ RARCH_WARN("Going to default to first audio driver...\n");
+
+ driver.audio = audio_driver_find_handle(0);
+
+ if (!driver.audio)
+ rarch_fail(1, "find_audio_driver()");
+ }
+}
+
+void uninit_audio(void)
+{
+ if (driver.audio_data && driver.audio)
+ driver.audio->free(driver.audio_data);
+
+ free(g_extern.audio_data.conv_outsamples);
+ g_extern.audio_data.conv_outsamples = NULL;
+ g_extern.audio_data.data_ptr = 0;
+
+ free(g_extern.audio_data.rewind_buf);
+ g_extern.audio_data.rewind_buf = NULL;
+
+ if (!g_settings.audio.enable)
+ {
+ driver.audio_active = false;
+ return;
+ }
+
+ rarch_resampler_freep(&driver.resampler,
+ &driver.resampler_data);
+
+ free(g_extern.audio_data.data);
+ g_extern.audio_data.data = NULL;
+
+ free(g_extern.audio_data.outsamples);
+ g_extern.audio_data.outsamples = NULL;
+
+ rarch_main_command(RARCH_CMD_DSP_FILTER_DEINIT);
+
+ compute_audio_buffer_statistics();
+}
+
+void init_audio(void)
+{
+ size_t outsamples_max, max_bufsamples = AUDIO_CHUNK_SIZE_NONBLOCKING * 2;
+
+ audio_convert_init_simd();
+
+ /* Resource leaks will follow if audio is initialized twice. */
+ if (driver.audio_data)
+ return;
+
+ /* Accomodate rewind since at some point we might have two full buffers. */
+ outsamples_max = max_bufsamples * AUDIO_MAX_RATIO *
+ g_settings.slowmotion_ratio;
+
+ /* Used for recording even if audio isn't enabled. */
+ rarch_assert(g_extern.audio_data.conv_outsamples =
+ (int16_t*)malloc(outsamples_max * sizeof(int16_t)));
+
+ g_extern.audio_data.block_chunk_size = AUDIO_CHUNK_SIZE_BLOCKING;
+ g_extern.audio_data.nonblock_chunk_size = AUDIO_CHUNK_SIZE_NONBLOCKING;
+ g_extern.audio_data.chunk_size =
+ g_extern.audio_data.block_chunk_size;
+
+ /* Needs to be able to hold full content of a full max_bufsamples
+ * in addition to its own. */
+ rarch_assert(g_extern.audio_data.rewind_buf = (int16_t*)
+ malloc(max_bufsamples * sizeof(int16_t)));
+ g_extern.audio_data.rewind_size = max_bufsamples;
+
+ if (!g_settings.audio.enable)
+ {
+ driver.audio_active = false;
+ return;
+ }
+
+ find_audio_driver();
+#ifdef HAVE_THREADS
+ if (g_extern.system.audio_callback.callback)
+ {
+ RARCH_LOG("Starting threaded audio driver ...\n");
+ if (!rarch_threaded_audio_init(&driver.audio, &driver.audio_data,
+ *g_settings.audio.device ? g_settings.audio.device : NULL,
+ g_settings.audio.out_rate, g_settings.audio.latency,
+ driver.audio))
+ {
+ RARCH_ERR("Cannot open threaded audio driver ... Exiting ...\n");
+ rarch_fail(1, "init_audio()");
+ }
+ }
+ else
+#endif
+ {
+ driver.audio_data = driver.audio->init(*g_settings.audio.device ?
+ g_settings.audio.device : NULL,
+ g_settings.audio.out_rate, g_settings.audio.latency);
+ }
+
+ if (!driver.audio_data)
+ {
+ RARCH_ERR("Failed to initialize audio driver. Will continue without audio.\n");
+ driver.audio_active = false;
+ }
+
+ g_extern.audio_data.use_float = false;
+ if (driver.audio_active && driver.audio->use_float(driver.audio_data))
+ g_extern.audio_data.use_float = true;
+
+ if (!g_settings.audio.sync && driver.audio_active)
+ {
+ rarch_main_command(RARCH_CMD_AUDIO_SET_NONBLOCKING_STATE);
+ g_extern.audio_data.chunk_size =
+ g_extern.audio_data.nonblock_chunk_size;
+ }
+
+ if (g_extern.audio_data.in_rate <= 0.0f)
+ {
+ /* Should never happen. */
+ RARCH_WARN("Input rate is invalid (%.3f Hz). Using output rate (%u Hz).\n",
+ g_extern.audio_data.in_rate, g_settings.audio.out_rate);
+ g_extern.audio_data.in_rate = g_settings.audio.out_rate;
+ }
+
+ g_extern.audio_data.orig_src_ratio =
+ g_extern.audio_data.src_ratio =
+ (double)g_settings.audio.out_rate / g_extern.audio_data.in_rate;
+
+ if (!rarch_resampler_realloc(&driver.resampler_data,
+ &driver.resampler,
+ g_settings.audio.resampler, g_extern.audio_data.orig_src_ratio))
+ {
+ RARCH_ERR("Failed to initialize resampler \"%s\".\n",
+ g_settings.audio.resampler);
+ driver.audio_active = false;
+ }
+
+ rarch_assert(g_extern.audio_data.data = (float*)
+ malloc(max_bufsamples * sizeof(float)));
+
+ g_extern.audio_data.data_ptr = 0;
+
+ rarch_assert(g_settings.audio.out_rate <
+ g_extern.audio_data.in_rate * AUDIO_MAX_RATIO);
+ rarch_assert(g_extern.audio_data.outsamples = (float*)
+ malloc(outsamples_max * sizeof(float)));
+
+ g_extern.audio_data.rate_control = false;
+ if (!g_extern.system.audio_callback.callback && driver.audio_active &&
+ g_settings.audio.rate_control)
+ {
+ if (driver.audio->buffer_size && driver.audio->write_avail)
+ {
+ g_extern.audio_data.driver_buffer_size =
+ driver.audio->buffer_size(driver.audio_data);
+ g_extern.audio_data.rate_control = true;
+ }
+ else
+ RARCH_WARN("Audio rate control was desired, but driver does not support needed features.\n");
+ }
+
+ rarch_main_command(RARCH_CMD_DSP_FILTER_DEINIT);
+
+ g_extern.measure_data.buffer_free_samples_count = 0;
+
+ if (driver.audio_active && !g_extern.audio_data.mute &&
+ g_extern.system.audio_callback.callback)
+ {
+ /* Threaded driver is initially stopped. */
+ driver.audio->start(driver.audio_data);
+ }
+}
diff --git a/audio_driver.h b/audio_driver.h
new file mode 100644
index 0000000000..91fc2a8139
--- /dev/null
+++ b/audio_driver.h
@@ -0,0 +1,117 @@
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ * Copyright (C) 2011-2015 - Daniel De Matteis
+ *
+ * RetroArch is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with RetroArch.
+ * If not, see .
+ */
+
+#ifndef __AUDIO_DRIVER__H
+#define __AUDIO_DRIVER__H
+
+#include
+#include
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct audio_driver
+{
+ void *(*init)(const char *device, unsigned rate, unsigned latency);
+
+ ssize_t (*write)(void *data, const void *buf, size_t size);
+
+ bool (*stop)(void *data);
+
+ bool (*start)(void *data);
+
+ /* Is the audio driver currently running? */
+ bool (*alive)(void *data);
+
+ /* Should we care about blocking in audio thread? Fast forwarding. */
+ void (*set_nonblock_state)(void *data, bool toggle);
+
+ void (*free)(void *data);
+
+ /* Defines if driver will take standard floating point samples,
+ * or int16_t samples. */
+ bool (*use_float)(void *data);
+
+ /* Human-readable identifier. */
+ const char *ident;
+
+ /* Optional. */
+ size_t (*write_avail)(void *data);
+
+ size_t (*buffer_size)(void *data);
+} audio_driver_t;
+
+extern audio_driver_t audio_rsound;
+extern audio_driver_t audio_oss;
+extern audio_driver_t audio_alsa;
+extern audio_driver_t audio_alsathread;
+extern audio_driver_t audio_roar;
+extern audio_driver_t audio_openal;
+extern audio_driver_t audio_opensl;
+extern audio_driver_t audio_jack;
+extern audio_driver_t audio_sdl;
+extern audio_driver_t audio_xa;
+extern audio_driver_t audio_pulse;
+extern audio_driver_t audio_dsound;
+extern audio_driver_t audio_coreaudio;
+extern audio_driver_t audio_xenon360;
+extern audio_driver_t audio_ps3;
+extern audio_driver_t audio_gx;
+extern audio_driver_t audio_psp1;
+extern audio_driver_t audio_rwebaudio;
+extern audio_driver_t audio_null;
+
+/**
+ * audio_driver_find_handle:
+ * @index : index of driver to get handle to.
+ *
+ * Returns: handle to audio driver at index. Can be NULL
+ * if nothing found.
+ **/
+const void *audio_driver_find_handle(int index);
+
+/**
+ * audio_driver_find_ident:
+ * @index : index of driver to get handle to.
+ *
+ * Returns: Human-readable identifier of audio driver at index. Can be NULL
+ * if nothing found.
+ **/
+const char *audio_driver_find_ident(int index);
+
+/**
+ * config_get_audio_driver_options:
+ *
+ * Get an enumerated list of all audio driver names, separated by '|'.
+ *
+ * Returns: string listing of all audio driver names, separated by '|'.
+ **/
+const char* config_get_audio_driver_options(void);
+
+void find_audio_driver(void);
+
+void uninit_audio(void);
+
+void init_audio(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/driver.c b/driver.c
index 792e8b5d78..621029a701 100644
--- a/driver.c
+++ b/driver.c
@@ -14,7 +14,6 @@
* If not, see .
*/
-
#include "driver.h"
#include "general.h"
#include "retroarch.h"
@@ -23,9 +22,7 @@
#include
#include
#include "compat/posix_string.h"
-#include "audio/utils.h"
#include "gfx/video_thread_wrapper.h"
-#include "audio/audio_thread_wrapper.h"
#include "gfx/gfx_common.h"
#include
@@ -43,129 +40,6 @@
driver_t driver;
-static const audio_driver_t *audio_drivers[] = {
-#ifdef HAVE_ALSA
- &audio_alsa,
-#ifndef __QNX__
- &audio_alsathread,
-#endif
-#endif
-#if defined(HAVE_OSS) || defined(HAVE_OSS_BSD)
- &audio_oss,
-#endif
-#ifdef HAVE_RSOUND
- &audio_rsound,
-#endif
-#ifdef HAVE_COREAUDIO
- &audio_coreaudio,
-#endif
-#ifdef HAVE_AL
- &audio_openal,
-#endif
-#ifdef HAVE_SL
- &audio_opensl,
-#endif
-#ifdef HAVE_ROAR
- &audio_roar,
-#endif
-#ifdef HAVE_JACK
- &audio_jack,
-#endif
-#if defined(HAVE_SDL) || defined(HAVE_SDL2)
- &audio_sdl,
-#endif
-#ifdef HAVE_XAUDIO
- &audio_xa,
-#endif
-#ifdef HAVE_DSOUND
- &audio_dsound,
-#endif
-#ifdef HAVE_PULSE
- &audio_pulse,
-#endif
-#ifdef __CELLOS_LV2__
- &audio_ps3,
-#endif
-#ifdef XENON
- &audio_xenon360,
-#endif
-#ifdef GEKKO
- &audio_gx,
-#endif
-#ifdef EMSCRIPTEN
- &audio_rwebaudio,
-#endif
-#ifdef PSP
- &audio_psp1,
-#endif
- &audio_null,
- NULL,
-};
-
-/**
- * audio_driver_find_handle:
- * @index : index of driver to get handle to.
- *
- * Returns: handle to audio driver at index. Can be NULL
- * if nothing found.
- **/
-static const void *audio_driver_find_handle(int index)
-{
- const void *drv = audio_drivers[index];
- if (!drv)
- return NULL;
- return drv;
-}
-
-/**
- * audio_driver_find_ident:
- * @index : index of driver to get handle to.
- *
- * Returns: Human-readable identifier of audio driver at index. Can be NULL
- * if nothing found.
- **/
-static const char *audio_driver_find_ident(int index)
-{
- const audio_driver_t *drv = audio_drivers[index];
- if (!drv)
- return NULL;
- return drv->ident;
-}
-
-/**
- * config_get_audio_driver_options:
- *
- * Get an enumerated list of all audio driver names, separated by '|'.
- *
- * Returns: string listing of all audio driver names, separated by '|'.
- **/
-const char* config_get_audio_driver_options(void)
-{
- union string_list_elem_attr attr;
- unsigned i;
- char *options = NULL;
- int options_len = 0;
- struct string_list *options_l = string_list_new();
-
- attr.i = 0;
-
- for (i = 0; audio_driver_find_handle(i); i++)
- {
- const char *opt = audio_driver_find_ident(i);
- options_len += strlen(opt) + 1;
- string_list_append(options_l, opt, attr);
- }
-
- options = (char*)calloc(options_len, sizeof(char));
-
- string_list_join_concat(options, options_len, options_l, "|");
-
- string_list_free(options_l);
- options_l = NULL;
-
- return options;
-}
-
static const video_driver_t *video_drivers[] = {
#ifdef HAVE_OPENGL
&video_gl,
@@ -824,7 +698,7 @@ static const void *find_driver_nonempty(const char *label, int i,
* Returns: -1 if no driver based on @label and @drv found, otherwise
* index number of the driver found in the array.
**/
-static int find_driver_index(const char * label, const char *drv)
+int find_driver_index(const char * label, const char *drv)
{
unsigned i;
char str[PATH_MAX_LENGTH];
@@ -1207,30 +1081,6 @@ static void find_menu_driver(void)
}
#endif
-
-static void find_audio_driver(void)
-{
- int i = find_driver_index("audio_driver", g_settings.audio.driver);
- if (i >= 0)
- driver.audio = audio_driver_find_handle(i);
- else
- {
- unsigned d;
- RARCH_ERR("Couldn't find any audio driver named \"%s\"\n",
- g_settings.audio.driver);
- RARCH_LOG_OUTPUT("Available audio drivers are:\n");
- for (d = 0; audio_driver_find_handle(d); d++)
- RARCH_LOG_OUTPUT("\t%s\n", audio_driver_find_ident(d));
- RARCH_WARN("Going to default to first audio driver...\n");
-
- driver.audio = audio_driver_find_handle(0);
-
- if (!driver.audio)
- rarch_fail(1, "find_audio_driver()");
- }
-}
-
-
static void find_video_driver(void)
{
int i;
@@ -1536,137 +1386,6 @@ static void init_menu(void)
}
#endif
-static void init_audio(void)
-{
- size_t outsamples_max, max_bufsamples = AUDIO_CHUNK_SIZE_NONBLOCKING * 2;
-
- audio_convert_init_simd();
-
- /* Resource leaks will follow if audio is initialized twice. */
- if (driver.audio_data)
- return;
-
- /* Accomodate rewind since at some point we might have two full buffers. */
- outsamples_max = max_bufsamples * AUDIO_MAX_RATIO *
- g_settings.slowmotion_ratio;
-
- /* Used for recording even if audio isn't enabled. */
- rarch_assert(g_extern.audio_data.conv_outsamples =
- (int16_t*)malloc(outsamples_max * sizeof(int16_t)));
-
- g_extern.audio_data.block_chunk_size = AUDIO_CHUNK_SIZE_BLOCKING;
- g_extern.audio_data.nonblock_chunk_size = AUDIO_CHUNK_SIZE_NONBLOCKING;
- g_extern.audio_data.chunk_size =
- g_extern.audio_data.block_chunk_size;
-
- /* Needs to be able to hold full content of a full max_bufsamples
- * in addition to its own. */
- rarch_assert(g_extern.audio_data.rewind_buf = (int16_t*)
- malloc(max_bufsamples * sizeof(int16_t)));
- g_extern.audio_data.rewind_size = max_bufsamples;
-
- if (!g_settings.audio.enable)
- {
- driver.audio_active = false;
- return;
- }
-
- find_audio_driver();
-#ifdef HAVE_THREADS
- if (g_extern.system.audio_callback.callback)
- {
- RARCH_LOG("Starting threaded audio driver ...\n");
- if (!rarch_threaded_audio_init(&driver.audio, &driver.audio_data,
- *g_settings.audio.device ? g_settings.audio.device : NULL,
- g_settings.audio.out_rate, g_settings.audio.latency,
- driver.audio))
- {
- RARCH_ERR("Cannot open threaded audio driver ... Exiting ...\n");
- rarch_fail(1, "init_audio()");
- }
- }
- else
-#endif
- {
- driver.audio_data = driver.audio->init(*g_settings.audio.device ?
- g_settings.audio.device : NULL,
- g_settings.audio.out_rate, g_settings.audio.latency);
- }
-
- if (!driver.audio_data)
- {
- RARCH_ERR("Failed to initialize audio driver. Will continue without audio.\n");
- driver.audio_active = false;
- }
-
- g_extern.audio_data.use_float = false;
- if (driver.audio_active && driver.audio->use_float(driver.audio_data))
- g_extern.audio_data.use_float = true;
-
- if (!g_settings.audio.sync && driver.audio_active)
- {
- rarch_main_command(RARCH_CMD_AUDIO_SET_NONBLOCKING_STATE);
- g_extern.audio_data.chunk_size =
- g_extern.audio_data.nonblock_chunk_size;
- }
-
- if (g_extern.audio_data.in_rate <= 0.0f)
- {
- /* Should never happen. */
- RARCH_WARN("Input rate is invalid (%.3f Hz). Using output rate (%u Hz).\n",
- g_extern.audio_data.in_rate, g_settings.audio.out_rate);
- g_extern.audio_data.in_rate = g_settings.audio.out_rate;
- }
-
- g_extern.audio_data.orig_src_ratio =
- g_extern.audio_data.src_ratio =
- (double)g_settings.audio.out_rate / g_extern.audio_data.in_rate;
-
- if (!rarch_resampler_realloc(&driver.resampler_data,
- &driver.resampler,
- g_settings.audio.resampler, g_extern.audio_data.orig_src_ratio))
- {
- RARCH_ERR("Failed to initialize resampler \"%s\".\n",
- g_settings.audio.resampler);
- driver.audio_active = false;
- }
-
- rarch_assert(g_extern.audio_data.data = (float*)
- malloc(max_bufsamples * sizeof(float)));
-
- g_extern.audio_data.data_ptr = 0;
-
- rarch_assert(g_settings.audio.out_rate <
- g_extern.audio_data.in_rate * AUDIO_MAX_RATIO);
- rarch_assert(g_extern.audio_data.outsamples = (float*)
- malloc(outsamples_max * sizeof(float)));
-
- g_extern.audio_data.rate_control = false;
- if (!g_extern.system.audio_callback.callback && driver.audio_active &&
- g_settings.audio.rate_control)
- {
- if (driver.audio->buffer_size && driver.audio->write_avail)
- {
- g_extern.audio_data.driver_buffer_size =
- driver.audio->buffer_size(driver.audio_data);
- g_extern.audio_data.rate_control = true;
- }
- else
- RARCH_WARN("Audio rate control was desired, but driver does not support needed features.\n");
- }
-
- rarch_main_command(RARCH_CMD_DSP_FILTER_DEINIT);
-
- g_extern.measure_data.buffer_free_samples_count = 0;
-
- if (driver.audio_active && !g_extern.audio_data.mute &&
- g_extern.system.audio_callback.callback)
- {
- /* Threaded driver is initially stopped. */
- driver.audio->start(driver.audio_data);
- }
-}
-
static void deinit_pixel_converter(void)
{
scaler_ctx_gen_reset(&driver.scaler);
@@ -2063,89 +1782,6 @@ static void compute_monitor_fps_statistics(void)
}
}
-/**
- * compute_audio_buffer_statistics:
- *
- * Computes audio buffer statistics.
- *
- **/
-static void compute_audio_buffer_statistics(void)
-{
- unsigned i, low_water_size, high_water_size, avg, stddev;
- float avg_filled, deviation;
- uint64_t accum = 0, accum_var = 0;
- unsigned low_water_count = 0, high_water_count = 0;
- unsigned samples = min(g_extern.measure_data.buffer_free_samples_count,
- AUDIO_BUFFER_FREE_SAMPLES_COUNT);
-
- if (samples < 3)
- return;
-
- for (i = 1; i < samples; i++)
- accum += g_extern.measure_data.buffer_free_samples[i];
-
- avg = accum / (samples - 1);
-
- for (i = 1; i < samples; i++)
- {
- int diff = avg - g_extern.measure_data.buffer_free_samples[i];
- accum_var += diff * diff;
- }
-
- stddev = (unsigned)sqrt((double)accum_var / (samples - 2));
- avg_filled = 1.0f - (float)avg / g_extern.audio_data.driver_buffer_size;
- deviation = (float)stddev / g_extern.audio_data.driver_buffer_size;
-
- low_water_size = g_extern.audio_data.driver_buffer_size * 3 / 4;
- high_water_size = g_extern.audio_data.driver_buffer_size / 4;
-
- for (i = 1; i < samples; i++)
- {
- if (g_extern.measure_data.buffer_free_samples[i] >= low_water_size)
- low_water_count++;
- else if (g_extern.measure_data.buffer_free_samples[i] <= high_water_size)
- high_water_count++;
- }
-
- RARCH_LOG("Average audio buffer saturation: %.2f %%, standard deviation (percentage points): %.2f %%.\n",
- avg_filled * 100.0, deviation * 100.0);
- RARCH_LOG("Amount of time spent close to underrun: %.2f %%. Close to blocking: %.2f %%.\n",
- (100.0 * low_water_count) / (samples - 1),
- (100.0 * high_water_count) / (samples - 1));
-}
-
-static void uninit_audio(void)
-{
- if (driver.audio_data && driver.audio)
- driver.audio->free(driver.audio_data);
-
- free(g_extern.audio_data.conv_outsamples);
- g_extern.audio_data.conv_outsamples = NULL;
- g_extern.audio_data.data_ptr = 0;
-
- free(g_extern.audio_data.rewind_buf);
- g_extern.audio_data.rewind_buf = NULL;
-
- if (!g_settings.audio.enable)
- {
- driver.audio_active = false;
- return;
- }
-
- rarch_resampler_freep(&driver.resampler,
- &driver.resampler_data);
-
- free(g_extern.audio_data.data);
- g_extern.audio_data.data = NULL;
-
- free(g_extern.audio_data.outsamples);
- g_extern.audio_data.outsamples = NULL;
-
- rarch_main_command(RARCH_CMD_DSP_FILTER_DEINIT);
-
- compute_audio_buffer_statistics();
-}
-
static void uninit_video_input(void)
{
rarch_main_command(RARCH_CMD_OVERLAY_DEINIT);
diff --git a/driver.h b/driver.h
index 930f3036a7..72a61ce679 100644
--- a/driver.h
+++ b/driver.h
@@ -14,7 +14,6 @@
* If not, see .
*/
-
#ifndef __DRIVER__H
#define __DRIVER__H
@@ -36,6 +35,8 @@
#include "frontend/frontend_context.h"
#include
+#include "audio_driver.h"
+
#include "menu/menu_driver.h"
#include "menu/backend/menu_backend.h"
#include "menu/disp/menu_display.h"
@@ -180,30 +181,6 @@ typedef struct video_info
bool rgb32;
} video_info_t;
-typedef struct audio_driver
-{
- void *(*init)(const char *device, unsigned rate, unsigned latency);
- ssize_t (*write)(void *data, const void *buf, size_t size);
- bool (*stop)(void *data);
- bool (*start)(void *data);
-
- /* Is the audio driver currently running? */
- bool (*alive)(void *data);
-
- /* Should we care about blocking in audio thread? Fast forwarding. */
- void (*set_nonblock_state)(void *data, bool toggle);
- void (*free)(void *data);
-
- /* Defines if driver will take standard floating point samples,
- * or int16_t samples. */
- bool (*use_float)(void *data);
- const char *ident;
-
- /* Optional. */
- size_t (*write_avail)(void *data);
- size_t (*buffer_size)(void *data);
-} audio_driver_t;
-
#define AXIS_NEG(x) (((uint32_t)(x) << 16) | UINT16_C(0xFFFF))
#define AXIS_POS(x) ((uint32_t)(x) | UINT32_C(0xFFFF0000))
#define AXIS_NONE UINT32_C(0xFFFFFFFF)
@@ -805,26 +782,6 @@ bool driver_update_system_av_info(const struct retro_system_av_info *info);
extern driver_t driver;
/* Backends */
-extern audio_driver_t audio_rsound;
-extern audio_driver_t audio_oss;
-extern audio_driver_t audio_alsa;
-extern audio_driver_t audio_alsathread;
-extern audio_driver_t audio_roar;
-extern audio_driver_t audio_openal;
-extern audio_driver_t audio_opensl;
-extern audio_driver_t audio_jack;
-extern audio_driver_t audio_sdl;
-extern audio_driver_t audio_xa;
-extern audio_driver_t audio_pulse;
-extern audio_driver_t audio_dsound;
-extern audio_driver_t audio_coreaudio;
-extern audio_driver_t audio_xenon360;
-extern audio_driver_t audio_ps3;
-extern audio_driver_t audio_gx;
-extern audio_driver_t audio_psp1;
-extern audio_driver_t audio_rwebaudio;
-extern audio_driver_t audio_null;
-
extern video_driver_t video_gl;
extern video_driver_t video_psp1;
extern video_driver_t video_vita;
@@ -886,15 +843,6 @@ const char* config_get_camera_driver_options(void);
**/
const char* config_get_video_driver_options(void);
-/**
- * config_get_audio_driver_options:
- *
- * Get an enumerated list of all audio driver names, separated by '|'.
- *
- * Returns: string listing of all audio driver names, separated by '|'.
- **/
-const char* config_get_audio_driver_options(void);
-
/**
* config_get_osk_driver_options:
*
@@ -929,6 +877,18 @@ const char* config_get_location_driver_options(void);
**/
const char* config_get_menu_driver_options(void);
#endif
+
+/**
+ * find_driver_index:
+ * @label : string of driver type to be found.
+ * @drv : identifier of driver to be found.
+ *
+ * Find index of the driver, based on @label.
+ *
+ * Returns: -1 if no driver based on @label and @drv found, otherwise
+ * index number of the driver found in the array.
+ **/
+int find_driver_index(const char * label, const char *drv);
extern camera_driver_t camera_v4l2;
extern camera_driver_t camera_android;
diff --git a/griffin/griffin.c b/griffin/griffin.c
index a950d92a08..ff537384c5 100644
--- a/griffin/griffin.c
+++ b/griffin/griffin.c
@@ -496,6 +496,7 @@ AUDIO
/*============================================================
DRIVERS
============================================================ */
+#include "../audio_driver.c"
#include "../driver.c"
/*============================================================