Skip to content

Instantly share code, notes, and snippets.

@atsushieno
Created March 9, 2018 10:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save atsushieno/539e4e14d4eafcad724e446ad73dc1ad to your computer and use it in GitHub Desktop.
Save atsushieno/539e4e14d4eafcad724e446ad73dc1ad to your computer and use it in GitHub Desktop.
diff --git a/fluidsynth/configure.ac b/fluidsynth/configure.ac
index 6067119..a1e1df7 100644
--- a/fluidsynth/configure.ac
+++ b/fluidsynth/configure.ac
@@ -226,6 +226,27 @@ if test "x${enable_aufile_support}" != "xno"; then
fi
+dnl
+dnl - Check support for OpenSLES
+dnl
+AC_CHECK_HEADER(SLES/OpenSLES_Android.h, OPENSLES_FOUND="yes",
+ OPENSLES_FOUND="no")
+AC_ARG_ENABLE(opensles, AS_HELP_STRING([--disable-opensles],
+ [disable OpenSLES support (default=auto)]),
+ enable_opensles=$enableval, enable_opensles="yes")
+
+OPENSLES_SUPPORT=0
+if test "$enable_opensles" = "yes" -a "$OPENSLES_FOUND" = "yes"; then
+ AC_DEFINE(OPENSLES_SUPPORT, 1, [whether or not we are supporting OpenSLES])
+ OPENSLES_SUPPORT=1
+ OPENSLES_LIBS="-lOpenSLES"
+fi
+
+AM_CONDITIONAL(OPENSLES_SUPPORT, test "$OPENSLES_SUPPORT" = "1")
+AC_SUBST(OPENSLES_LIBS)
+
+
+
dnl - Check for PulseAudio support
AC_ARG_ENABLE(pulse-support, AS_HELP_STRING([--disable-pulse-support],
@@ -519,6 +540,12 @@ else
echo "D-Bus: no"
fi
+if test "${OPENSLES_SUPPORT}" = "1"; then
+ echo "OpenSLES: yes"
+else
+ echo "OpenSLES: no"
+fi
+
if test "${PULSE_SUPPORT}" = "1"; then
echo "PulseAudio: yes"
else
diff --git a/fluidsynth/src/CMakeLists.txt b/fluidsynth/src/CMakeLists.txt
index e60037a..a3ffe2a 100644
--- a/fluidsynth/src/CMakeLists.txt
+++ b/fluidsynth/src/CMakeLists.txt
@@ -42,6 +42,11 @@ if ( READLINE_SUPPORT )
include_directories ( ${READLINE_INCLUDE_DIR} )
endif ( READLINE_SUPPORT )
+if ( OPENSLES_SUPPORT )
+ set ( fluid_opensles_SOURCES drivers/fluid_opensles.c )
+ include_directories ( ${OPENSLES_INCLUDEDIR} ${OPENSLES_INCLUDE_DIRS} )
+endif ( OPENSLES_SUPPORT )
+
if ( PULSE_SUPPORT )
set ( fluid_pulse_SOURCES drivers/fluid_pulse.c )
include_directories ( ${PULSE_INCLUDEDIR} ${PULSE_INCLUDE_DIRS} )
@@ -217,6 +222,8 @@ link_directories (
${JACK_LIBRARY_DIRS}
${ALSA_LIBDIR}
${ALSA_LIBRARY_DIRS}
+ ${OPENSLES_LIBDIR}
+ ${OPENSLES_LIBRARY_DIRS}
${PULSE_LIBDIR}
${PULSE_LIBRARY_DIRS}
${PORTAUDIO_LIBDIR}
@@ -241,6 +248,7 @@ add_library ( libfluidsynth
${fluid_lash_SOURCES}
${fluid_ladspa_SOURCES}
${fluid_midishare_SOURCES}
+ ${fluid_opensles_SOURCES}
${fluid_oss_SOURCES}
${fluid_portaudio_SOURCES}
${fluid_pulse_SOURCES}
@@ -293,6 +301,7 @@ target_link_libraries ( libfluidsynth
${LADCCA_LIBRARIES}
${JACK_LIBRARIES}
${ALSA_LIBRARIES}
+ ${OPENSLES_LIBRARIES}
${PULSE_LIBRARIES}
${PORTAUDIO_LIBRARIES}
${LIBSNDFILE_LIBRARIES}
diff --git a/fluidsynth/src/Makefile.am b/fluidsynth/src/Makefile.am
index 5244322..4c50491 100644
--- a/fluidsynth/src/Makefile.am
+++ b/fluidsynth/src/Makefile.am
@@ -4,6 +4,10 @@ AUTOMAKE_OPTIONS = subdir-objects
# Tests for optional drivers
+if OPENSLES_SUPPORT
+fluid_opensles = drivers/fluid_opensles.c
+endif
+
if PULSE_SUPPORT
fluid_pulse = drivers/fluid_pulse.c
endif
@@ -65,6 +69,7 @@ EXTRA_DIST = fluid_dll.c \
drivers/fluid_dsound.c \
drivers/fluid_jack.c \
drivers/fluid_midishare.c \
+ drivers/fluid_opensles.c \
drivers/fluid_oss.c \
drivers/fluid_portaudio.c \
drivers/fluid_pulse.c \
@@ -90,6 +95,7 @@ libfluidsynth_la_SOURCES = \
$(fluid_jack) \
$(fluid_ladspa) \
$(fluid_lash) \
+ $(fluid_opensles) \
$(fluid_oss) \
$(fluid_portaudio) \
$(fluid_pulse) \
@@ -176,12 +182,12 @@ INCLUDES = -I$(top_srcdir)/include \
$(LASH_CFLAGS) $(LADCCA_CFLAGS) \
$(READLINE_CFLAGS) $(JACK_CFLAGS) $(ALSA_CFLAGS) $(PULSE_CFLAGS) \
$(PORTAUDIO_CFLAGS) $(DART_CFLAGS) $(GLIB_CFLAGS) $(LIBSNDFILE_CFLAGS) \
- $(DBUS_CFLAGS)
+ $(DBUS_CFLAGS) $(OPENSLES_CFLAGS)
libfluidsynth_la_LIBADD = $(LIBFLUID_LIBS) $(LASH_LIBS) $(LADCCA_LIBS) \
$(READLINE_LIBS) $(COREAUDIO_LIBS) $(COREMIDI_LIBS) $(JACK_LIBS) \
$(ALSA_LIBS) $(PULSE_LIBS) $(PORTAUDIO_LIBS) $(DART_LIBS) \
- $(GLIB_LIBS) $(LIBSNDFILE_LIBS) $(DBUS_LIBS)
+ $(GLIB_LIBS) $(LIBSNDFILE_LIBS) $(DBUS_LIBS) $(OPENSLES_LIBS)
libfluidsynth_la_LDFLAGS = \
-version-info @LT_VERSION_INFO@ \
diff --git a/fluidsynth/src/config.cmake b/fluidsynth/src/config.cmake
index b622def..72f3cac 100644
--- a/fluidsynth/src/config.cmake
+++ b/fluidsynth/src/config.cmake
@@ -181,6 +181,9 @@
/* Define to enable PortAudio driver */
#cmakedefine PORTAUDIO_SUPPORT @PORTAUDIO_SUPPORT@
+/* Define to enable OpenSLES driver */
+#cmakedefine OPENSLES_SUPPORT @OPENSLES_SUPPORT@
+
/* Define to enable PulseAudio driver */
#cmakedefine PULSE_SUPPORT @PULSE_SUPPORT@
diff --git a/fluidsynth/src/drivers/fluid_adriver.c b/fluidsynth/src/drivers/fluid_adriver.c
index ecf9efa..71ce493 100644
--- a/fluidsynth/src/drivers/fluid_adriver.c
+++ b/fluidsynth/src/drivers/fluid_adriver.c
@@ -37,6 +37,13 @@ typedef struct _fluid_audriver_definition_t
} fluid_audriver_definition_t;
+#if OPENSLES_SUPPORT
+fluid_audio_driver_t* new_fluid_opensles_audio_driver(fluid_settings_t* settings,
+ fluid_synth_t* synth);
+int delete_fluid_opensles_audio_driver(fluid_audio_driver_t* p);
+void fluid_opensles_audio_driver_settings(fluid_settings_t* settings);
+#endif
+
#if PULSE_SUPPORT
fluid_audio_driver_t* new_fluid_pulse_audio_driver(fluid_settings_t* settings,
fluid_synth_t* synth);
@@ -141,6 +148,13 @@ fluid_audriver_definition_t fluid_audio_drivers[] = {
delete_fluid_oss_audio_driver,
fluid_oss_audio_driver_settings },
#endif
+#if OPENSLES_SUPPORT
+ { "opensles",
+ new_fluid_opensles_audio_driver,
+ NULL,
+ delete_fluid_opensles_audio_driver,
+ fluid_opensles_audio_driver_settings },
+#endif
#if PULSE_SUPPORT
{ "pulseaudio",
new_fluid_pulse_audio_driver,
@@ -227,6 +241,8 @@ void fluid_audio_driver_settings(fluid_settings_t* settings)
fluid_settings_register_str(settings, "audio.driver", "jack", 0, NULL, NULL);
#elif ALSA_SUPPORT
fluid_settings_register_str(settings, "audio.driver", "alsa", 0, NULL, NULL);
+#elif OPENSLES_SUPPORT
+ fluid_settings_register_str(settings, "audio.driver", "opensles", 0, NULL, NULL);
#elif PULSE_SUPPORT
fluid_settings_register_str(settings, "audio.driver", "pulseaudio", 0, NULL, NULL);
#elif OSS_SUPPORT
@@ -248,6 +264,9 @@ void fluid_audio_driver_settings(fluid_settings_t* settings)
#endif
/* Add all drivers to the list of options */
+#if OPENSLES_SUPPORT
+ fluid_settings_add_option(settings, "audio.driver", "opensles");
+#endif
#if PULSE_SUPPORT
fluid_settings_add_option(settings, "audio.driver", "pulseaudio");
#endif
diff --git a/fluidsynth/src/drivers/fluid_opensles.c b/fluidsynth/src/drivers/fluid_opensles.c
new file mode 100644
index 0000000..1a3fcd2
--- /dev/null
+++ b/fluidsynth/src/drivers/fluid_opensles.c
@@ -0,0 +1,444 @@
+/* FluidSynth - A Software Synthesizer
+ *
+ * Copyright (C) 2003 Peter Hanappe and others.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+/* fluid_opensles.c
+ *
+ * Audio driver for OpenSLES.
+ *
+ */
+
+#include "fluid_synth.h"
+#include "fluid_adriver.h"
+#include "fluid_settings.h"
+
+#include "config.h"
+
+#include <sys/time.h>
+#include <SLES/OpenSLES.h>
+#include <SLES/OpenSLES_Android.h>
+
+#define NUM_CHANNELS 2
+
+/** fluid_opensles_audio_driver_t
+ *
+ * This structure should not be accessed directly. Use audio port
+ * functions instead.
+ */
+typedef struct {
+ fluid_audio_driver_t driver;
+ SLObjectItf engine;
+ SLObjectItf output_mix_object;
+ SLObjectItf audio_player;
+ SLPlayItf audio_player_interface;
+ SLAndroidSimpleBufferQueueItf player_buffer_queue_interface;
+
+ void* data;
+ int buffer_size;
+
+ int is_sample_format_float;
+ int use_callback_mode;
+
+ /* used only by callback mode */
+ short* short_buffer;
+ short* short_callback_buffer_l;
+ short* short_callback_buffer_r;
+ float* float_buffer;
+ float* float_callback_buffer_l;
+ float* float_callback_buffer_r;
+ fluid_audio_func_t callback;
+ /* used only by non-callback mode */
+ fluid_thread_t *thread;
+
+ int cont;
+ long next_expected_enqueue_time;
+
+ double sample_rate;
+} fluid_opensles_audio_driver_t;
+
+
+fluid_audio_driver_t* new_fluid_opensles_audio_driver(fluid_settings_t* settings,
+ fluid_synth_t* synth);
+fluid_audio_driver_t* new_fluid_opensles_audio_driver2(fluid_settings_t* settings,
+ fluid_audio_func_t func, void* data);
+int delete_fluid_opensles_audio_driver(fluid_audio_driver_t* p);
+void fluid_opensles_audio_driver_settings(fluid_settings_t* settings);
+static void fluid_opensles_audio_run(void* d);
+static void fluid_opensles_audio_run2(void* d);
+static void fluid_opensles_callback(SLAndroidSimpleBufferQueueItf caller, void *pContext);
+void fluid_opensles_adjust_latency(fluid_opensles_audio_driver_t* dev);
+
+
+void fluid_opensles_audio_driver_settings(fluid_settings_t* settings)
+{
+ fluid_settings_register_int(settings, "audio.opensles.use-callback-mode", 0, 0, 1,
+ FLUID_HINT_TOGGLED, NULL, NULL);
+}
+
+
+/*
+ * new_fluid_opensles_audio_driver
+ */
+fluid_audio_driver_t*
+new_fluid_opensles_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
+{
+ return new_fluid_opensles_audio_driver2 (settings,
+ (fluid_audio_func_t) fluid_synth_process,
+ (void*) synth);
+}
+
+/*
+ * new_fluid_opensles_audio_driver2
+ */
+fluid_audio_driver_t*
+new_fluid_opensles_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, void* data)
+{
+ SLresult result;
+ fluid_opensles_audio_driver_t* dev;
+ double sample_rate;
+ int period_size;
+ int realtime_prio = 0;
+ int err;
+ int is_sample_format_float;
+ int use_callback_mode;
+
+ fluid_synth_t* synth = (fluid_synth_t*) data;
+
+ dev = FLUID_NEW(fluid_opensles_audio_driver_t);
+ if (dev == NULL) {
+ FLUID_LOG(FLUID_ERR, "Out of memory");
+ return NULL;
+ }
+
+ FLUID_MEMSET(dev, 0, sizeof(fluid_opensles_audio_driver_t));
+
+ fluid_settings_getint(settings, "audio.period-size", &period_size);
+ fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate);
+ fluid_settings_getint(settings, "audio.realtime-prio", &realtime_prio);
+ is_sample_format_float = fluid_settings_str_equal (settings, "audio.sample-format", "float");
+ fluid_settings_getint(settings, "audio.opensles.use-callback-mode", &use_callback_mode);
+
+ dev->data = synth;
+ dev->use_callback_mode = use_callback_mode;
+ dev->is_sample_format_float = is_sample_format_float;
+ dev->buffer_size = period_size;
+ dev->sample_rate = sample_rate;
+ dev->cont = 1;
+
+ result = slCreateEngine (&(dev->engine), 0, NULL, 0, NULL, NULL);
+
+ if (!dev->engine)
+ {
+ FLUID_LOG(FLUID_ERR, "Failed to create OpenSLES connection");
+ goto error_recovery;
+ }
+ result = (*dev->engine)->Realize (dev->engine, SL_BOOLEAN_FALSE);
+ if (result != 0) goto error_recovery;
+
+ SLEngineItf engine_interface;
+ result = (*dev->engine)->GetInterface (dev->engine, SL_IID_ENGINE, &engine_interface);
+ if (result != 0) goto error_recovery;
+
+ result = (*engine_interface)->CreateOutputMix (engine_interface, &dev->output_mix_object, 0, 0, 0);
+ if (result != 0) goto error_recovery;
+
+ result = (*dev->output_mix_object)->Realize (dev->output_mix_object, SL_BOOLEAN_FALSE);
+ if (result != 0) goto error_recovery;
+
+ SLDataLocator_AndroidSimpleBufferQueue loc_buffer_queue = {
+ SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
+ 2 /* number of buffers */
+ };
+ SLDataFormat_PCM format_pcm = {
+ SL_DATAFORMAT_PCM,
+ NUM_CHANNELS,
+ ((SLuint32) sample_rate) * 1000,
+ SL_PCMSAMPLEFORMAT_FIXED_16,
+ SL_PCMSAMPLEFORMAT_FIXED_16,
+ SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT,
+ SL_BYTEORDER_LITTLEENDIAN
+ };
+ SLDataSource audio_src = {
+ &loc_buffer_queue,
+ &format_pcm
+ };
+
+ SLDataLocator_OutputMix loc_outmix = {
+ SL_DATALOCATOR_OUTPUTMIX,
+ dev->output_mix_object
+ };
+ SLDataSink audio_sink = {&loc_outmix, NULL};
+
+ const SLInterfaceID ids1[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};
+ const SLboolean req1[] = {SL_BOOLEAN_TRUE};
+ result = (*engine_interface)->CreateAudioPlayer (engine_interface,
+ &(dev->audio_player), &audio_src, &audio_sink, 1, ids1, req1);
+ if (result != 0) goto error_recovery;
+
+ result = (*dev->audio_player)->Realize (dev->audio_player,SL_BOOLEAN_FALSE);
+ if (result != 0) goto error_recovery;
+
+ result = (*dev->audio_player)->GetInterface (dev->audio_player,
+ SL_IID_PLAY, &(dev->audio_player_interface));
+ if (result != 0) goto error_recovery;
+
+ result = (*dev->audio_player)->GetInterface(dev->audio_player,
+ SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &(dev->player_buffer_queue_interface));
+ if (result != 0) goto error_recovery;
+
+ if (dev->use_callback_mode) {
+
+ if (dev->is_sample_format_float)
+ dev->float_buffer = FLUID_ARRAY(float, dev->buffer_size * NUM_CHANNELS);
+ else
+ dev->short_buffer = FLUID_ARRAY(short, dev->buffer_size * NUM_CHANNELS);
+ if (dev->float_buffer == NULL && dev->short_buffer == NULL)
+ {
+ FLUID_LOG(FLUID_ERR, "Out of memory.");
+ return;
+ }
+
+ if (dev->callback) {
+
+ if (dev->is_sample_format_float)
+ dev->float_callback_buffer_l = FLUID_ARRAY(float, dev->buffer_size);
+ else
+ dev->short_callback_buffer_l = FLUID_ARRAY(short, dev->buffer_size);
+ if (dev->float_callback_buffer_l == NULL && dev->short_callback_buffer_l == NULL)
+ {
+ FLUID_LOG(FLUID_ERR, "Out of memory.");
+ return;
+ }
+
+ if (dev->is_sample_format_float)
+ dev->float_callback_buffer_r = FLUID_ARRAY(float, dev->buffer_size);
+ else
+ dev->short_callback_buffer_r = FLUID_ARRAY(short, dev->buffer_size);
+ if (dev->float_callback_buffer_r == NULL && dev->short_callback_buffer_r == NULL)
+ {
+ FLUID_LOG(FLUID_ERR, "Out of memory.");
+ return;
+ }
+ }
+
+ result = (*dev->player_buffer_queue_interface)->RegisterCallback(dev->player_buffer_queue_interface, fluid_opensles_callback, dev);
+ if (result != 0) goto error_recovery;
+
+ if (dev->is_sample_format_float)
+ (*dev->player_buffer_queue_interface)->Enqueue(dev->player_buffer_queue_interface, dev->float_buffer, dev->buffer_size * NUM_CHANNELS * sizeof(float));
+ else
+ (*dev->player_buffer_queue_interface)->Enqueue(dev->player_buffer_queue_interface, dev->short_buffer, dev->buffer_size * NUM_CHANNELS * sizeof(short));
+
+ (*dev->audio_player_interface)->SetCallbackEventsMask(dev->audio_player_interface, SL_PLAYEVENT_HEADATEND);
+ result = (*dev->audio_player_interface)->SetPlayState(dev->audio_player_interface, SL_PLAYSTATE_PLAYING);
+ if (result != 0) goto error_recovery;
+
+ } else { /* non-callback mode */
+
+ result = (*dev->audio_player_interface)->SetPlayState(dev->audio_player_interface, SL_PLAYSTATE_PLAYING);
+ if (result != 0) goto error_recovery;
+
+ /* Create the audio thread */
+ dev->thread = new_fluid_thread ("opensles-audio", fluid_opensles_audio_run,
+ dev, realtime_prio, FALSE);
+ if (!dev->thread)
+ goto error_recovery;
+ }
+
+ FLUID_LOG(FLUID_INFO, "Using OpenSLES driver");
+
+ return (fluid_audio_driver_t*) dev;
+
+ error_recovery:
+ delete_fluid_opensles_audio_driver((fluid_audio_driver_t*) dev);
+ return NULL;
+}
+
+int delete_fluid_opensles_audio_driver(fluid_audio_driver_t* p)
+{
+ fluid_opensles_audio_driver_t* dev = (fluid_opensles_audio_driver_t*) p;
+
+ if (dev == NULL) {
+ return FLUID_OK;
+ }
+
+ dev->cont = 0;
+
+ if (!dev->use_callback_mode) {
+ if (dev->thread)
+ fluid_thread_join (dev->thread);
+ }
+
+ if (dev->audio_player)
+ (*dev->audio_player)->Destroy (dev->audio_player);
+ if (dev->output_mix_object)
+ (*dev->output_mix_object)->Destroy (dev->output_mix_object);
+ if (dev->engine)
+ (*dev->engine)->Destroy (dev->engine);
+
+ if (dev->use_callback_mode) {
+ if (dev->is_sample_format_float) {
+ if (dev->float_callback_buffer_l)
+ FLUID_FREE(dev->float_callback_buffer_l);
+ if (dev->float_callback_buffer_r)
+ FLUID_FREE(dev->float_callback_buffer_r);
+ if (dev->float_buffer)
+ FLUID_FREE(dev->float_buffer);
+ } else {
+ if (dev->short_callback_buffer_l)
+ FLUID_FREE(dev->short_callback_buffer_l);
+ if (dev->short_callback_buffer_r)
+ FLUID_FREE(dev->short_callback_buffer_r);
+ if (dev->short_buffer)
+ FLUID_FREE(dev->short_buffer);
+ }
+ }
+
+ FLUID_FREE(dev);
+
+ return FLUID_OK;
+}
+
+void fluid_opensles_adjust_latency(fluid_opensles_audio_driver_t* dev)
+{
+ struct timespec ts;
+ long current_time, wait_in_theory;
+
+ wait_in_theory = 1000000 * dev->buffer_size / dev->sample_rate;
+
+ /* compute delta time and update 'next expected enqueue' time */
+ clock_gettime(CLOCK_REALTIME, &ts);
+ current_time = ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
+ long time_delta = dev->next_expected_enqueue_time == 0 ? 0 : dev->next_expected_enqueue_time - current_time;
+ if (time_delta == 0)
+ dev->next_expected_enqueue_time += current_time + wait_in_theory;
+ else
+ dev->next_expected_enqueue_time += wait_in_theory;
+ /* take some sleep only if it's running ahead */
+ if (time_delta > 0)
+ usleep (time_delta);
+}
+
+void fluid_opensles_callback(SLAndroidSimpleBufferQueueItf caller, void *pContext)
+{
+ fluid_opensles_audio_driver_t* dev = (fluid_opensles_audio_driver_t*) pContext;
+
+ short *short_buf = dev->short_buffer;
+ float *float_buf = dev->float_buffer;
+ int buffer_size;
+ int i, k;
+ int err;
+ float *float_callback_buffers[2];
+ SLresult result;
+
+ buffer_size = dev->buffer_size;
+
+ fluid_opensles_adjust_latency(dev);
+
+ if (dev->callback)
+ {
+ if (dev->is_sample_format_float) {
+ float* left = dev->float_callback_buffer_l;
+ float* right = dev->float_callback_buffer_r;
+ float_callback_buffers [0] = left;
+ float_callback_buffers [1] = right;
+
+ (*dev->callback)(dev->data, buffer_size, 0, NULL, 2, float_callback_buffers);
+
+ for (i = 0, k = 0; i < buffer_size; i++) {
+ float_buf[k++] = left[i];
+ float_buf[k++] = right[i];
+ }
+ } else {
+ FLUID_LOG(FLUID_ERR, "callback is not supported when audio.sample-format is '16bits'.");
+ }
+ }
+ else {
+ if (dev->is_sample_format_float)
+ fluid_synth_write_float(dev->data, buffer_size, float_buf, 0, 2, float_buf, 1, 2);
+ else
+ fluid_synth_write_s16(dev->data, buffer_size, short_buf, 0, 2, short_buf, 1, 2);
+ }
+
+ if (dev->is_sample_format_float)
+ result = (*caller)->Enqueue (
+ dev->player_buffer_queue_interface, float_buf, buffer_size * sizeof (float) * NUM_CHANNELS);
+ else
+ result = (*caller)->Enqueue (
+ dev->player_buffer_queue_interface, short_buf, buffer_size * sizeof (short) * NUM_CHANNELS);
+ if (result != 0) {
+ err = result;
+ /* Do not simply break at just one single insufficient buffer. Go on. */
+ }
+}
+
+/* Thread without audio callback, more efficient */
+static void
+fluid_opensles_audio_run(void* d)
+{
+ fluid_opensles_audio_driver_t* dev = (fluid_opensles_audio_driver_t*) d;
+ short *short_buf = NULL;
+ float *float_buf = NULL;
+ int buffer_size;
+ int err;
+ SLresult result;
+
+ buffer_size = dev->buffer_size;
+
+ /* FIXME - Probably shouldn't alloc in run() */
+ if (dev->is_sample_format_float)
+ float_buf = FLUID_ARRAY(float, buffer_size * NUM_CHANNELS);
+ else
+ short_buf = FLUID_ARRAY(short, buffer_size * NUM_CHANNELS);
+
+ if (short_buf == NULL && float_buf == NULL)
+ {
+ FLUID_LOG(FLUID_ERR, "Out of memory.");
+ return;
+ }
+
+ int cnt = 0;
+
+ while (dev->cont)
+ {
+ fluid_opensles_adjust_latency (dev);
+
+ /* it seems that the synth keeps emitting synthesized buffers even if there is no sound. So keep feeding... */
+ if (dev->is_sample_format_float)
+ fluid_synth_write_float(dev->data, buffer_size, float_buf, 0, 2, float_buf, 1, 2);
+ else
+ fluid_synth_write_s16(dev->data, buffer_size, short_buf, 0, 2, short_buf, 1, 2);
+
+ if (dev->is_sample_format_float)
+ result = (*dev->player_buffer_queue_interface)->Enqueue (
+ dev->player_buffer_queue_interface, float_buf, buffer_size * sizeof (float) * NUM_CHANNELS);
+ else
+ result = (*dev->player_buffer_queue_interface)->Enqueue (
+ dev->player_buffer_queue_interface, short_buf, buffer_size * sizeof (short) * NUM_CHANNELS);
+ if (result != 0) {
+ err = result;
+ /* Do not simply break at just one single insufficient buffer. Go on. */
+ }
+ } /* while (dev->cont) */
+
+ if (dev->is_sample_format_float)
+ FLUID_FREE(float_buf);
+ else
+ FLUID_FREE(short_buf);
+}
diff --git a/fluidsynth/src/utils/fluid_sys.c b/fluidsynth/src/utils/fluid_sys.c
index ee7d8d9..7af517b 100644
--- a/fluidsynth/src/utils/fluid_sys.c
+++ b/fluidsynth/src/utils/fluid_sys.c
@@ -30,6 +30,10 @@
#include "fluid_rtkit.h"
#endif
+#ifdef ANDROID
+#include <android/log.h>
+#endif
+
/* WIN32 HACK - Flag used to differentiate between a file descriptor and a socket.
* Should work, so long as no SOCKET or file descriptor ends up with this bit set. - JG */
#define WIN32_SOCKET_FLAG 0x40000000
@@ -151,24 +155,48 @@ fluid_default_log_function(int level, char* message, void* data)
switch (level) {
case FLUID_PANIC:
+#ifdef ANDROID
+ __android_log_write(ANDROID_LOG_FATAL, fluid_libname, message);
+#else
FLUID_FPRINTF(out, "%s: panic: %s\n", fluid_libname, message);
+#endif
break;
case FLUID_ERR:
+#ifdef ANDROID
+ __android_log_write(ANDROID_LOG_ERROR, fluid_libname, message);
+#else
FLUID_FPRINTF(out, "%s: error: %s\n", fluid_libname, message);
+#endif
break;
case FLUID_WARN:
+#ifdef ANDROID
+ __android_log_write(ANDROID_LOG_WARN, fluid_libname, message);
+#else
FLUID_FPRINTF(out, "%s: warning: %s\n", fluid_libname, message);
+#endif
break;
case FLUID_INFO:
+#ifdef ANDROID
+ __android_log_write(ANDROID_LOG_INFO, fluid_libname, message);
+#else
FLUID_FPRINTF(out, "%s: %s\n", fluid_libname, message);
+#endif
break;
case FLUID_DBG:
#if DEBUG
+#ifdef ANDROID
+ __android_log_write(ANDROID_LOG_DEBUG, fluid_libname, message);
+#else
FLUID_FPRINTF(out, "%s: debug: %s\n", fluid_libname, message);
+#endif
#endif
break;
default:
+#ifdef ANDROID
+ __android_log_write(ANDROID_LOG_VERBOSE, fluid_libname, message);
+#else
FLUID_FPRINTF(out, "%s: %s\n", fluid_libname, message);
+#endif
break;
}
fflush(out);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment