Added libsndfile support to fluid_filerenderer.c with file type, audio format and endian byte order options.

Added 3 additional parameters to new_fluid_file_renderer() for specifying audio format options.
Added public functions fluid_file_renderer_get_(type/format/endian)_names.
Added new settings options "audio.file.(type/format/endian)".
fluid_aufile.c updated to use new file renderer.
fluid_settings_add_option and fluid_settings_remove_option now use const char *.
Added FLUID_N_ELEMENTS and FLUID_MUTEX_INIT to fluid_sys.h.
Added -E, -O and -T command line options and help for file rendering options.
Re-organized --help output to be lower case letter before upper case.
Added FLUID_STRRCHR to fluidsynth_priv.h.
This commit is contained in:
Josh Green 2009-10-03 18:12:19 +00:00
parent 43a9923dff
commit e0a18f7c2a
11 changed files with 577 additions and 87 deletions

View file

@ -157,6 +157,25 @@ PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.10 gthread-2.0 >= 2.10)
AC_SUBST(GLIB_CFLAGS)
AC_SUBST(GLIB_LIBS)
dnl Check for libsndfile support
AC_ARG_ENABLE(libsndfile-support, AS_HELP_STRING([--disable-libsndfile-support],
[Do not compile libsndfile support (default=auto)]),
enable_libsndfile_support=$enableval, enable_libsndfile_support="yes")
if test "x$enable_libsndfile_support" != "xno"; then
PKG_CHECK_MODULES(LIBSNDFILE, sndfile >= 1.0.0, LIBSNDFILE_SUPPORT=1, LIBSNDFILE_SUPPORT=0)
else
LIBSNDFILE_SUPPORT=0
fi
if test "$LIBSNDFILE_SUPPORT" = "1"; then
AC_DEFINE(LIBSNDFILE_SUPPORT, 1, [Define to enable libsndfile support])
fi
AM_CONDITIONAL(LIBSNDFILE_SUPPORT, test "$LIBSNDFILE_SUPPORT" = "1")
AC_SUBST(LIBSNDFILE_CFLAGS)
AC_SUBST(LIBSNDFILE_LIBS)
dnl
dnl Check support for all the drivers
@ -423,6 +442,12 @@ echo
echo "**************************************************************"
echo "Summary:"
if test "${LIBSNDFILE_SUPPORT}" = "1"; then
echo "libsndfile: yes"
else
echo "libsndfile: no (raw audio file rendering only)"
fi
if test "${PULSE_SUPPORT}" = "1"; then
echo "PulseAudio: yes"
else

View file

@ -67,11 +67,15 @@ FLUIDSYNTH_API void delete_fluid_audio_driver(fluid_audio_driver_t* driver);
FLUIDSYNTH_API void fluid_audio_driver_get_names(char* buf, size_t buflen, const char* separator);
FLUIDSYNTH_API fluid_file_renderer_t* new_fluid_file_renderer(fluid_synth_t* synth,
char* filename, int period_size);
FLUIDSYNTH_API fluid_file_renderer_t *new_fluid_file_renderer(fluid_synth_t* synth,
char* filename, char* type,
char* format, char* endian,
int period_size);
FLUIDSYNTH_API int fluid_file_renderer_process_block(fluid_file_renderer_t* dev);
FLUIDSYNTH_API void delete_fluid_file_renderer(fluid_file_renderer_t* dev);
FLUIDSYNTH_API const char **fluid_file_renderer_get_type_names (void);
FLUIDSYNTH_API const char **fluid_file_renderer_get_format_names (void);
FLUIDSYNTH_API const char **fluid_file_renderer_get_endian_names (void);
#ifdef __cplusplus
}

View file

@ -126,12 +126,12 @@ libfluidsynth_la_SOURCES = \
INCLUDES = -I$(top_srcdir)/include $(LASH_CFLAGS) $(LADCCA_CFLAGS) \
$(READLINE_CFLAGS) $(JACK_CFLAGS) $(ALSA_CFLAGS) $(PULSE_CFLAGS) \
$(PORTAUDIO_CFLAGS) $(DART_CFLAGS) $(GLIB_CFLAGS)
$(PORTAUDIO_CFLAGS) $(DART_CFLAGS) $(GLIB_CFLAGS) $(LIBSNDFILE_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)
$(GLIB_LIBS) $(LIBSNDFILE_LIBS)
libfluidsynth_la_LDFLAGS = \
-version-info @LT_VERSION_INFO@ \

View file

@ -132,6 +132,9 @@
/* Include the LADSPA Fx unit */
#undef LADSPA
/* Define to enable libsndfile support */
#undef LIBSNDFILE_SUPPORT
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#undef LT_OBJDIR

View file

@ -27,6 +27,7 @@
#include "fluid_adriver.h"
#include "fluid_settings.h"
#include "fluid_sys.h"
#include "config.h"
#include <stdio.h>
@ -62,7 +63,36 @@ static int fluid_file_audio_run_s16(void* d, unsigned int msec);
void fluid_file_audio_driver_settings(fluid_settings_t* settings)
{
#if LIBSNDFILE_SUPPORT
const char **names, **np;
int i;
#endif
#if LIBSNDFILE_SUPPORT
fluid_settings_register_str(settings, "audio.file.name", "fluidsynth.wav", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.file.type", "auto", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.file.format", "s16", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.file.endian", "auto", 0, NULL, NULL);
fluid_settings_add_option (settings, "audio.file.type", "auto");
names = fluid_file_renderer_get_type_names ();
for (np = names; *np; np++)
fluid_settings_add_option(settings, "audio.file.type", *np);
names = fluid_file_renderer_get_format_names ();
for (np = names; *np; np++)
fluid_settings_add_option(settings, "audio.file.format", *np);
names = fluid_file_renderer_get_endian_names ();
for (np = names; *np; np++)
fluid_settings_add_option(settings, "audio.file.endian", *np);
#else
fluid_settings_register_str(settings, "audio.file.name", "fluidsynth.raw", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.file.type", "raw", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.file.format", "s16", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.file.endian", "cpu", 0, NULL, NULL);
#endif
}
@ -72,7 +102,7 @@ new_fluid_file_audio_driver(fluid_settings_t* settings,
{
fluid_file_audio_driver_t* dev;
int err;
char* filename = NULL;
char* filename = NULL, *type = NULL, *format = NULL, *endian = NULL;
int msec;
dev = FLUID_NEW(fluid_file_audio_driver_t);
@ -94,14 +124,21 @@ new_fluid_file_audio_driver(fluid_settings_t* settings,
goto error_recovery;
}
dev->renderer = new_fluid_file_renderer(synth, filename, dev->period_size);
fluid_settings_dupstr (settings, "audio.file.type", &type); /* ++ alloc file type */
fluid_settings_dupstr (settings, "audio.file.format", &format); /* ++ alloc file format */
fluid_settings_dupstr (settings, "audio.file.endian", &endian); /* ++ alloc file endian */
dev->renderer = new_fluid_file_renderer(synth, filename, type, format, endian,
dev->period_size);
if (filename) FLUID_FREE (filename); /* -- free filename */
if (type) FLUID_FREE (type); /* -- free type */
if (format) FLUID_FREE (format); /* -- free format */
if (endian) FLUID_FREE (endian); /* -- free endian */
if (dev->renderer == NULL) {
if (filename) FLUID_FREE (filename); /* -- free filename */
goto error_recovery;
}
if (filename) FLUID_FREE (filename); /* -- free filename */
msec = (int) (0.5 + dev->period_size / dev->sample_rate * 1000.0);
dev->timer = new_fluid_timer(msec, fluid_file_audio_run_s16, (void*) dev, TRUE, FALSE, TRUE);
if (dev->timer == NULL) {

View file

@ -24,15 +24,203 @@
#include <stdio.h>
#include "fluidsynth_priv.h"
#include "fluid_synth.h"
#include "fluid_sys.h"
#if LIBSNDFILE_SUPPORT
#include <sndfile.h>
#endif
struct _fluid_file_renderer_t {
FILE* file;
fluid_synth_t* synth;
#if LIBSNDFILE_SUPPORT
SNDFILE* sndfile;
float* buf;
#else
FILE* file;
short* buf;
#endif
int period_size;
int buf_size;
};
#if LIBSNDFILE_SUPPORT
/* Default file type used, if none specified and auto extension search fails */
#define FLUID_FILE_RENDERER_DEFAULT_FILE_TYPE SF_FORMAT_WAV
/* File audio format names.
* !! Keep in sync with format_ids[] */
const char *format_names[] = {
"s8",
"s16",
"s24",
"s32",
"u8",
"float",
"double",
NULL /* Terminator */
};
/* File audio format IDs.
* !! Keep in sync with format_names[] */
const int format_ids[] = {
SF_FORMAT_PCM_S8,
SF_FORMAT_PCM_16,
SF_FORMAT_PCM_24,
SF_FORMAT_PCM_32,
SF_FORMAT_PCM_U8,
SF_FORMAT_FLOAT,
SF_FORMAT_DOUBLE
};
/* File endian byte order names.
* !! Keep in sync with endian_ids[] */
const char *endian_names[] = {
"auto",
"little",
"big",
"cpu",
NULL
};
/* File endian byte order ids.
* !! Keep in sync with endian_names[] */
const int endian_ids[] = {
SF_ENDIAN_FILE,
SF_ENDIAN_LITTLE,
SF_ENDIAN_BIG,
SF_ENDIAN_CPU
};
static int fluid_file_renderer_parse_options (char *filetype, char *format,
char *endian, char *filename, SF_INFO *info);
static int fluid_file_renderer_find_file_type (char *extension, int *type);
#else /* No libsndfile support */
/* File type names. */
char *type_names[] = {
"raw",
NULL /* Terminator */
};
/* File audio format names. */
char *format_names[] = {
"s16",
NULL /* Terminator */
};
/* File endian byte order names. */
char *endian_names[] = {
"cpu",
NULL
};
#endif
/**
* Create a new file renderer and open the file.
* @param synth The synth that creates audio data.
* @param filename Output filename
* @param type File type string or NULL for default "auto", which tries to
* determine format from filename extension or uses "wav".
* @param format Audio format string (can be empty or NULL for default format "s16")
* @param endian Endian specification or NULL for default "auto", which uses
* the file type's usual byte order.
* @param period_size Sample count, amount of samples to write to the file at
* every call to fluid_file_renderer_process_block().
* @return the new object, or NULL on failure
* @since: 1.1.0
*/
fluid_file_renderer_t *
new_fluid_file_renderer(fluid_synth_t* synth, char* filename, char* type,
char* format, char* endian, int period_size)
{
fluid_file_renderer_t* dev;
#if LIBSNDFILE_SUPPORT
SF_INFO info;
double samplerate;
#endif
dev = FLUID_NEW(fluid_file_renderer_t);
if (dev == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory");
return NULL;
}
FLUID_MEMSET(dev, 0, sizeof(fluid_file_renderer_t));
dev->synth = synth;
dev->period_size = period_size;
#if LIBSNDFILE_SUPPORT
dev->buf_size = 2 * dev->period_size * sizeof (float);
dev->buf = FLUID_ARRAY(float, 2 * dev->period_size);
#else
dev->buf_size = 2 * dev->period_size * sizeof (short);
dev->buf = FLUID_ARRAY(short, 2 * dev->period_size);
#endif
if (dev->buf == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory");
goto error_recovery;
}
if (filename == NULL) {
FLUID_LOG(FLUID_ERR, "No file name specified");
goto error_recovery;
}
#if LIBSNDFILE_SUPPORT
memset (&info, 0, sizeof (info));
info.format = FLUID_FILE_RENDERER_DEFAULT_FILE_TYPE | SF_FORMAT_PCM_16;
if (!fluid_file_renderer_parse_options (type, format, endian, filename, &info))
goto error_recovery;
fluid_settings_getnum (synth->settings, "synth.sample-rate", &samplerate);
info.samplerate = samplerate + 0.5;
info.channels = 2;
if (!sf_format_check (&info))
{
FLUID_LOG(FLUID_ERR, "Invalid or unsupported audio file format settings");
goto error_recovery;
}
dev->sndfile = sf_open (filename, SFM_WRITE, &info);
if (!dev->sndfile)
{
FLUID_LOG(FLUID_ERR, "Failed to open audio file '%s' for writing", filename);
goto error_recovery;
}
/* Turn on clipping and normalization of floats (-1.0 - 1.0) */
sf_command (dev->sndfile, SFC_SET_CLIPPING, NULL, SF_TRUE);
sf_command (dev->sndfile, SFC_SET_NORM_FLOAT, NULL, SF_TRUE);
#else
dev->file = fopen(filename, "wb");
if (dev->file == NULL) {
FLUID_LOG(FLUID_ERR, "Failed to open the file '%s'", filename);
goto error_recovery;
}
#endif
return dev;
error_recovery:
delete_fluid_file_renderer(dev);
return NULL;
}
/**
* Close file and destroy a file renderer object.
* @param dev File renderer object.
@ -44,9 +232,17 @@ void delete_fluid_file_renderer(fluid_file_renderer_t* dev)
return;
}
#if LIBSNDFILE_SUPPORT
if (dev->sndfile != NULL) {
int retval = sf_close (dev->sndfile);
if (retval != 0) FLUID_LOG (FLUID_WARN, "Error closing audio file: %s",
sf_error_number (retval));
}
#else
if (dev->file != NULL) {
fclose(dev->file);
}
#endif
if (dev->buf != NULL) {
FLUID_FREE(dev->buf);
@ -56,62 +252,32 @@ void delete_fluid_file_renderer(fluid_file_renderer_t* dev)
return;
}
/**
* Create a new file renderer and open the file.
* @param synth The synth that creates audio data.
* @param filename Output filename
* @param period_size Sample count, amount of samples to write to the file at
* every call to fluid_file_renderer_process_block().
* @return the new object, or NULL on failure
* @since: 1.1.0
*/
fluid_file_renderer_t* new_fluid_file_renderer(fluid_synth_t* synth, char* filename, int period_size)
{
fluid_file_renderer_t* dev;
dev = FLUID_NEW(fluid_file_renderer_t);
if (dev == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory");
return NULL;
}
FLUID_MEMSET(dev, 0, sizeof(fluid_file_renderer_t));
dev->synth = synth;
dev->period_size = period_size;
dev->buf_size = 2 * dev->period_size * sizeof(short);
dev->buf = FLUID_ARRAY(short, 2 * dev->period_size);
if (dev->buf == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory");
goto error_recovery;
}
if (filename == NULL) {
FLUID_LOG(FLUID_ERR, "No file name specified");
goto error_recovery;
}
dev->file = fopen(filename, "wb");
if (dev->file == NULL) {
FLUID_LOG(FLUID_ERR, "Failed to open the file '%s'", filename);
goto error_recovery;
}
return dev;
error_recovery:
delete_fluid_file_renderer(dev);
return NULL;
}
#if LIBSNDFILE_SUPPORT
/**
* Write period_size samples to file.
* @param dev File renderer instance
* @return FLUID_OK or FLUID_FAILED if an error occurred
* @since: 1.1.0
*/
int fluid_file_renderer_process_block(fluid_file_renderer_t* dev)
int
fluid_file_renderer_process_block(fluid_file_renderer_t* dev)
{
int n;
fluid_synth_write_float(dev->synth, dev->period_size, dev->buf, 0, 2, dev->buf, 1, 2);
n = sf_writef_float (dev->sndfile, dev->buf, dev->period_size);
if (n != dev->period_size) {
FLUID_LOG (FLUID_ERR, "Audio file write error: %s",
sf_strerror (dev->sndfile));
return FLUID_FAILED;
}
return FLUID_OK;
}
#else /* No libsndfile support */
int
fluid_file_renderer_process_block(fluid_file_renderer_t* dev)
{
int n, offset;
@ -129,3 +295,188 @@ int fluid_file_renderer_process_block(fluid_file_renderer_t* dev)
return FLUID_OK;
}
#endif
#if LIBSNDFILE_SUPPORT
/**
* Get NULL terminated list of supported audio file type names.
* @return NULL terminated list of strings which is internal and should not be
* modified or freed. NOTE: May return NULL if memory allocation fails.
*/
const char **
fluid_file_renderer_get_type_names (void)
{
static fluid_mutex_t mutex = FLUID_MUTEX_INIT;
static const char **type_names = NULL;
SF_FORMAT_INFO finfo;
int major_count;
int i, i2, index;
fluid_mutex_lock (mutex);
if (!type_names)
{
sf_command (NULL, SFC_GET_FORMAT_MAJOR_COUNT, &major_count, sizeof (int));
type_names = FLUID_ARRAY (const char *, major_count + 1);
if (type_names)
{
for (i = 0, index = 0; i < major_count; i++)
{
finfo.format = i;
sf_command (NULL, SFC_GET_FORMAT_MAJOR, &finfo, sizeof (finfo));
/* Check for duplicates */
for (i2 = 0; i2 < index; i2++)
if (strcmp (type_names[i2], finfo.extension) == 0)
break;
if (i2 < index) continue;
type_names[index++] = finfo.extension; /* Add name to array */
}
type_names[index] = NULL;
}
else FLUID_LOG (FLUID_ERR, "Out of memory");
}
fluid_mutex_unlock (mutex);
return (const char **)type_names;
}
#else
const char **
fluid_file_renderer_get_type_names (void)
{
return type_names;
}
#endif
const char **
fluid_file_renderer_get_format_names (void)
{
return format_names;
}
const char **
fluid_file_renderer_get_endian_names (void)
{
return endian_names;
}
#if LIBSNDFILE_SUPPORT
/**
* Parse a colon separated format string and configure an SF_INFO structure accordingly.
* @param filetype File type string (NULL or "auto" to attempt to identify format
* by filename extension, with fallback to "wav")
* @param format File audio format string or NULL to use "s16"
* @param endian File endian string or NULL to use "auto" which uses the file type's
* default endian byte order.
* @param filename File name (used by "auto" type to determine type, based on extension)
* @param info Audio file info structure to configure
* @return TRUE on success, FALSE otherwise
*/
static int
fluid_file_renderer_parse_options (char *filetype, char *format, char *endian,
char *filename, SF_INFO *info)
{
int type = -1; /* -1 indicates "auto" type */
char *s;
int i;
/* If "auto" type, then use extension to search for a match */
if (!filetype || FLUID_STRCMP (filetype, "auto") == 0)
{
type = FLUID_FILE_RENDERER_DEFAULT_FILE_TYPE;
s = FLUID_STRRCHR (filename, '.');
if (s && s[1] != '\0')
{
if (!fluid_file_renderer_find_file_type (s + 1, &type))
FLUID_LOG (FLUID_WARN, "Failed to determine audio file type from filename, defaulting to WAV");
}
}
else if (!fluid_file_renderer_find_file_type (filetype, &type))
{
FLUID_LOG(FLUID_ERR, "Invalid or unsupported audio file type '%s'", filetype);
return FALSE;
}
info->format = (info->format & ~SF_FORMAT_TYPEMASK) | type;
/* Look for subtype */
if (format)
{
for (i = 0; format_names[i]; i++)
if (FLUID_STRCMP (format, format_names[i]) == 0)
break;
if (!format_names[i])
{
FLUID_LOG (FLUID_ERR, "Invalid or unsupported file audio format '%s'", format);
return FALSE;
}
info->format = (info->format & ~SF_FORMAT_SUBMASK) | format_ids[i];
}
/* Look for endian */
if (endian)
{
for (i = 0; endian_names[i]; i++)
if (FLUID_STRCMP (endian, endian_names[i]) == 0)
break;
if (!endian_names[i])
{
FLUID_LOG (FLUID_ERR, "Invalid or unsupported endian byte order '%s'", endian);
return FALSE;
}
info->format = (info->format & ~SF_FORMAT_ENDMASK) | endian_ids[i];
}
return TRUE;
}
/**
* Searches for a supported libsndfile file type by extension.
* @param extension The extension string
* @param ext_len Length of the extension string
* @param type Location to store the type (unmodified if not found)
* @return TRUE if found, FALSE otherwise
*/
static int
fluid_file_renderer_find_file_type (char *extension, int *type)
{
SF_FORMAT_INFO finfo;
int major_count;
int i;
sf_command (NULL, SFC_GET_FORMAT_MAJOR_COUNT, &major_count, sizeof (int));
for (i = 0; i < major_count; i++)
{
finfo.format = i;
sf_command (NULL, SFC_GET_FORMAT_MAJOR, &finfo, sizeof (finfo));
if (FLUID_STRCMP (extension, finfo.extension) == 0)
break;
}
if (i < major_count)
{
*type = finfo.format;
return TRUE;
}
return FALSE;
}
#endif

View file

@ -944,7 +944,7 @@ fluid_settings_getstr_default(fluid_settings_t* settings, char* name)
* @return 1 if the setting exists and option was added, 0 otherwise
*/
int
fluid_settings_add_option(fluid_settings_t* settings, char* name, char* s)
fluid_settings_add_option(fluid_settings_t* settings, char* name, const char* s)
{
fluid_setting_node_t *node;
char* tokens[MAX_SETTINGS_TOKENS];
@ -981,7 +981,7 @@ fluid_settings_add_option(fluid_settings_t* settings, char* name, char* s)
* @return 1 if the setting exists and option was removed, 0 otherwise
*/
int
fluid_settings_remove_option(fluid_settings_t* settings, char* name, char* s)
fluid_settings_remove_option(fluid_settings_t* settings, char* name, const char* s)
{
fluid_setting_node_t *node;
char* tokens[MAX_SETTINGS_TOKENS];

View file

@ -25,10 +25,10 @@
/** returns 1 if the option was added, 0 otherwise */
int fluid_settings_add_option(fluid_settings_t* settings, char* name, char* s);
int fluid_settings_add_option(fluid_settings_t* settings, char* name, const char* s);
/** returns 1 if the option was added, 0 otherwise */
int fluid_settings_remove_option(fluid_settings_t* settings, char* name, char* s);
int fluid_settings_remove_option(fluid_settings_t* settings, char* name, const char* s);
typedef int (*fluid_num_update_t)(void* data, char* name, double value);

View file

@ -63,6 +63,7 @@ void fluid_time_config(void);
#define FLUID_UINT_TO_POINTER GUINT_TO_POINTER
#define FLUID_POINTER_TO_INT GPOINTER_TO_INT
#define FLUID_INT_TO_POINTER GINT_TO_POINTER
#define FLUID_N_ELEMENTS(struct) (sizeof (struct) / sizeof (struct[0]))
/*
@ -126,6 +127,7 @@ int fluid_timer_stop(fluid_timer_t* timer);
/* Regular mutex */
typedef GStaticMutex fluid_mutex_t;
#define FLUID_MUTEX_INIT G_STATIC_MUTEX_INIT
#define fluid_mutex_init(_m) g_static_mutex_init(&(_m))
#define fluid_mutex_destroy(_m) g_static_mutex_free(&(_m))
#define fluid_mutex_lock(_m) g_static_mutex_lock(&(_m))

View file

@ -176,24 +176,31 @@ settings_foreach_func (void *data, char *name, int type)
}
}
void fast_render_loop(fluid_settings_t* settings, fluid_synth_t* synth, fluid_player_t* player)
static void
fast_render_loop(fluid_settings_t* settings, fluid_synth_t* synth, fluid_player_t* player)
{
fluid_file_renderer_t* renderer;
char* filename = NULL;
char* filename = NULL, *type = NULL, *format = NULL, *endian = NULL;
int period_size = 0;
fluid_settings_getint(settings, "audio.period-size", &period_size);
fluid_settings_dupstr(settings, "audio.file.name", &filename); /* ++ alloc file name */
fluid_settings_dupstr (settings, "audio.file.type", &type); /* ++ alloc file type */
fluid_settings_dupstr (settings, "audio.file.format", &format); /* ++ alloc file format */
fluid_settings_dupstr (settings, "audio.file.endian", &endian); /* ++ alloc file endian */
if (filename == NULL || period_size <= 0) {
if (filename == NULL || type == NULL || format == NULL || endian == NULL || period_size <= 0) {
fprintf(stderr, "Failed to fetch parameters for file renderer\n");
if (filename) FLUID_FREE (filename); /* -- free file name */
return;
}
renderer = new_fluid_file_renderer(synth, filename, period_size);
renderer = new_fluid_file_renderer (synth, filename, type, format, endian, period_size);
FLUID_FREE (filename); /* -- free file name */
FLUID_FREE (type); /* -- free file type */
FLUID_FREE (format); /* -- free format */
FLUID_FREE (endian); /* -- free endian */
if (!renderer) {
return;
@ -235,9 +242,6 @@ int main(int argc, char** argv)
fluid_audio_driver_t* adriver = NULL;
fluid_synth_t* synth = NULL;
fluid_server_t* server = NULL;
char* midi_id = NULL;
char* midi_driver = NULL;
char* midi_device = NULL;
char* config_file = NULL;
int audio_groups = 0;
int audio_channels = 0;
@ -245,7 +249,7 @@ int main(int argc, char** argv)
int dump = 0;
int fast_render = 0;
int connect_lash = 1;
char *optchars = "a:C:c:df:F:G:g:hijK:L:lm:no:p:R:r:sVvz:";
char *optchars = "a:C:c:dE:f:F:G:g:hijK:L:lm:nO:o:p:R:r:sT:Vvz:";
#ifdef LASH_ENABLED
int enabled_lash = 0; /* set to TRUE if lash gets enabled */
fluid_lash_args_t *lash_args;
@ -266,6 +270,9 @@ int main(int argc, char** argv)
{"audio-bufsize", 1, 0, 'z'},
{"audio-channels", 1, 0, 'L'},
{"audio-driver", 1, 0, 'a'},
{"audio-file-endian", 1, 0, 'E'},
{"audio-file-format", 1, 0, 'O'},
{"audio-file-type", 1, 0, 'T'},
{"audio-groups", 1, 0, 'G'},
{"chorus", 1, 0, 'C'},
{"connect-jack-outputs", 0, 0, 'j'},
@ -352,6 +359,24 @@ int main(int argc, char** argv)
fluid_settings_setstr(settings, "synth.dump", "yes");
dump = 1;
break;
case 'E':
if (FLUID_STRCMP (optarg, "help") == 0)
{
const char **names = fluid_file_renderer_get_endian_names ();
const char **sp;
print_welcome ();
printf ("-E options (audio file byte order):\n ");
for (sp = names; *sp; sp++)
printf (" %s", *sp);
printf ("\n\nauto: Use audio file format's default endian byte order\n"
"cpu: Use CPU native byte order\n");
exit (0);
}
else fluid_settings_setstr(settings, "audio.file.endian", optarg);
break;
case 'f':
config_file = optarg;
break;
@ -390,6 +415,23 @@ int main(int argc, char** argv)
case 'n':
midi_in = 0;
break;
case 'O':
if (FLUID_STRCMP (optarg, "help") == 0)
{
const char **names = fluid_file_renderer_get_format_names ();
const char **sp;
print_welcome ();
printf ("-O options (file audio format):\n ");
for (sp = names; *sp; sp++)
printf (" %s", *sp);
printf ("\n");
exit (0);
}
else fluid_settings_setstr(settings, "audio.file.format", optarg);
break;
case 'o':
process_o_cmd_line_option(settings, optarg);
break;
@ -409,6 +451,25 @@ int main(int argc, char** argv)
case 's':
with_server = 1;
break;
case 'T':
if (FLUID_STRCMP (optarg, "help") == 0)
{
const char **names = fluid_file_renderer_get_type_names ();
const char **sp;
if (!names) exit (1); /* Can happen if out of memory */
print_welcome ();
printf ("-T options (audio file type):\n ");
for (sp = names; *sp; sp++)
printf (" %s", *sp);
printf ("\n\nauto: Determine type from file name extension, defaults to \"wav\"\n");
exit (0);
}
else fluid_settings_setstr(settings, "audio.file.type", optarg);
break;
case 'V':
printf("FluidSynth %s\n", VERSION);
exit (0);
@ -725,20 +786,22 @@ print_help()
printf(" -a, --audio-driver=[label]\n"
" The name of the audio driver to use.\n"
" Valid values: %s\n", allnames);
printf(" -C, --chorus\n"
" Turn the chorus on or off [0|1|yes|no, default = on]\n");
printf(" -c, --audio-bufcount=[count]\n"
" Number of audio buffers\n");
printf(" -C, --chorus\n"
" Turn the chorus on or off [0|1|yes|no, default = on]\n");
printf(" -d, --dump\n"
" Dump incoming and outgoing MIDI events to stdout\n");
printf(" -F, --fast-render=[file]\n"
" Render MIDI file to raw audio data and store in [file]\n");
printf(" -E, --audio-file-endian\n"
" Audio file endian for fast rendering or aufile driver (\"help\" for list)\n");
printf(" -f, --load-config\n"
" Load command configuration file (shell commands)\n");
printf(" -G, --audio-groups\n"
" Defines the number of LADSPA audio nodes\n");
printf(" -F, --fast-render=[file]\n"
" Render MIDI file to raw audio data and store in [file]\n");
printf(" -g, --gain\n"
" Set the master gain [0 < gain < 10, default = 0.2]\n");
printf(" -G, --audio-groups\n"
" Defines the number of LADSPA audio nodes\n");
printf(" -h, --help\n"
" Print out this help summary\n");
printf(" -i, --no-shell\n"
@ -747,32 +810,36 @@ print_help()
" Attempt to connect the jack outputs to the physical ports\n");
printf(" -K, --midi-channels=[num]\n"
" The number of midi channels [default = 16]\n");
printf(" -L, --audio-channels=[num]\n"
" The number of stereo audio channels [default = 1]\n");
#ifdef LASH_ENABLED
printf(" -l, --disable-lash\n"
" Don't connect to LASH server\n");
#endif
printf(" -L, --audio-channels=[num]\n"
" The number of stereo audio channels [default = 1]\n");
fluid_midi_driver_get_names(allnames, sizeof(allnames), ", ");
printf(" -m, --midi-driver=[label]\n"
" The name of the midi driver to use.\n"
" Valid values: %s\n", allnames);
printf(" -n, --no-midi-in\n"
" Don't create a midi driver to read MIDI input events [default = yes]\n");
printf(" -p, --portname=[label]\n"
" Set MIDI port name (alsa_seq, coremidi drivers)\n");
printf(" -o\n"
" Define a setting, -o name=value (\"-o help\" to dump current values)\n");
printf(" -R, --reverb\n"
" Turn the reverb on or off [0|1|yes|no, default = on]\n");
printf(" -O, --audio-file-format\n"
" Audio file format for fast rendering or aufile driver (\"help\" for list)\n");
printf(" -p, --portname=[label]\n"
" Set MIDI port name (alsa_seq, coremidi drivers)\n");
printf(" -r, --sample-rate\n"
" Set the sample rate\n");
printf(" -R, --reverb\n"
" Turn the reverb on or off [0|1|yes|no, default = on]\n");
printf(" -s, --server\n"
" Start FluidSynth as a server process\n");
printf(" -V, --version\n"
" Show version of program\n");
printf(" -T, --audio-file-type\n"
" Audio file type for fast rendering or aufile driver (\"help\" for list)\n");
printf(" -v, --verbose\n"
" Print out verbose messages about midi events\n");
printf(" -V, --version\n"
" Show version of program\n");
printf(" -z, --audio-bufsize=[size]\n"
" Size of each audio buffer\n");
exit(0);

View file

@ -232,6 +232,7 @@ typedef FILE* fluid_file;
#define FLUID_STRCPY(_dst,_src) strcpy(_dst,_src)
#define FLUID_STRNCPY(_dst,_src,_n) strncpy(_dst,_src,_n)
#define FLUID_STRCHR(_s,_c) strchr(_s,_c)
#define FLUID_STRRCHR(_s,_c) strrchr(_s,_c)
#ifdef strdup
#define FLUID_STRDUP(s) strdup(s)
#else