-
-
Save atsushieno/539e4e14d4eafcad724e446ad73dc1ad to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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