diff --git a/template/calfbox/configure.ac b/template/calfbox/configure.ac index 491698a..f0893e9 100644 --- a/template/calfbox/configure.ac +++ b/template/calfbox/configure.ac @@ -1,9 +1,9 @@ # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. -AC_PREREQ(2.63) +AC_PREREQ([2.71]) AC_INIT([calfbox],[0.0.3],[wdev@foltman.com]) -AC_CONFIG_HEADER([config.h]) +AC_CONFIG_HEADERS([config.h]) LT_INIT([]) LT_LANG([C]) @@ -14,12 +14,14 @@ if test "x$prefix" = "xNONE"; then fi # Checks for programs. -AC_PROG_CC_C99 +AC_PROG_CC AC_PROG_INSTALL PKG_PROG_PKG_CONFIG # Checks for headers. -AC_HEADER_STDC +AC_CHECK_INCLUDES_DEFAULT +AC_PROG_EGREP + # Set initial parameters PYTHON_ENABLED="yes" @@ -35,49 +37,49 @@ NEON_ENABLED="no" AC_MSG_CHECKING([whether to enable Python embedding]) AC_ARG_WITH(python, -AC_HELP_STRING([--without-python],[disable Python embedding]), +AS_HELP_STRING([--without-python],[disable Python embedding]), [if test "$withval" = "no"; then PYTHON_ENABLED="no"; fi],[]) AC_MSG_RESULT($PYTHON_ENABLED) AC_MSG_CHECKING([whether to enable ncurses UI]) AC_ARG_WITH(ncurses, -AC_HELP_STRING([--without-ncurses],[disable ncurses ui]), +AS_HELP_STRING([--without-ncurses],[disable ncurses ui]), [if test "$withval" = "no"; then NCURSES_ENABLED="no"; fi],[]) AC_MSG_RESULT($NCURSES_ENABLED) AC_MSG_CHECKING([whether to enable JACK I/O]) AC_ARG_WITH(jack, -AC_HELP_STRING([--without-jack],[disable JACK audio and MIDI]), +AS_HELP_STRING([--without-jack],[disable JACK audio and MIDI]), [if test "$withval" = "no"; then JACK_ENABLED="no"; fi],[]) AC_MSG_RESULT($JACK_ENABLED) AC_MSG_CHECKING([whether to enable Fluidsynth]) AC_ARG_WITH(fluidsynth, -AC_HELP_STRING([--without-fluidsynth],[disable use of Fluidsynth]), +AS_HELP_STRING([--without-fluidsynth],[disable use of Fluidsynth]), [if test "$withval" = "no"; then FLUIDSYNTH_ENABLED="no"; fi],[]) AC_MSG_RESULT($FLUIDSYNTH_ENABLED) AC_MSG_CHECKING([whether to enable libsmf]) AC_ARG_WITH(libsmf, -AC_HELP_STRING([--without-libsmf],[disable use of libsmf]), +AS_HELP_STRING([--without-libsmf],[disable use of libsmf]), [if test "$withval" = "no"; then LIBSMF_ENABLED="no"; fi],[]) AC_MSG_RESULT($LIBSMF_ENABLED) AC_MSG_CHECKING([whether to enable libusb]) AC_ARG_WITH(libusb, -AC_HELP_STRING([--without-libusb],[disable use of libusb]), +AS_HELP_STRING([--without-libusb],[disable use of libusb]), [if test "$withval" = "no"; then LIBUSB_ENABLED="no"; fi],[]) AC_MSG_RESULT($LIBUSB_ENABLED) AC_MSG_CHECKING([whether to enable SSE (x86 family only)]) AC_ARG_WITH(sse, -AC_HELP_STRING([--with-sse],[enable use of SSE]), +AS_HELP_STRING([--with-sse],[enable use of SSE]), [if test "$withval" = "yes"; then SSE_ENABLED="yes"; fi],[]) AC_MSG_RESULT($SSE_ENABLED) AC_MSG_CHECKING([whether to enable NEON (ARM family only)]) AC_ARG_WITH(neon, -AC_HELP_STRING([--with-neon],[enable use of NEON]), +AS_HELP_STRING([--with-neon],[enable use of NEON]), [if test "$withval" = "yes"; then NEON_ENABLED="yes"; fi],[]) AC_MSG_RESULT($NEON_ENABLED) diff --git a/template/calfbox/eq.h b/template/calfbox/eq.h index 2a5e070..f1f25ad 100644 --- a/template/calfbox/eq.h +++ b/template/calfbox/eq.h @@ -28,4 +28,4 @@ struct eq_band extern float cbox_eq_get_band_param(const char *cfg_section, int band, const char *param, float defvalue); extern float cbox_eq_get_band_param_db(const char *cfg_section, int band, const char *param, float defvalue); -extern void cbox_eq_reset_bands(struct cbox_biquadf_state (*state)[2], int bands); +extern void cbox_eq_reset_bands(struct cbox_biquadf_state state[1][2], int bands); diff --git a/template/calfbox/fluid.c b/template/calfbox/fluid.c index 20580e4..d0685ed 100644 --- a/template/calfbox/fluid.c +++ b/template/calfbox/fluid.c @@ -77,7 +77,10 @@ struct fluidsynth_module int sfid; int output_pairs; int is_multi; +#if OLD_FLUIDSYNTH float **left_outputs, **right_outputs; +#endif + GString *error_log; }; static gboolean select_patch_by_name(struct fluidsynth_module *m, int channel, const gchar *preset, GError **error) @@ -106,9 +109,35 @@ static gboolean select_patch_by_name(struct fluidsynth_module *m, int channel, c return FALSE; } +static void cbox_fluidsynth_log_write(int level, const char *message, void *data) +{ + struct fluidsynth_module *m = data; + if (!m->error_log) + m->error_log = g_string_new(message); + else + g_string_append(m->error_log, message); + g_string_append_c(m->error_log, '\n'); +} + +static gboolean load_soundfont(struct fluidsynth_module *m, const char *bank_name, GError **error) +{ + g_message("Loading soundfont %s", bank_name); + int result = fluid_synth_sfload(m->synth, bank_name, 1); + if (result == FLUID_FAILED) + { + char *error_msg = g_string_free(m->error_log, FALSE); + m->error_log = NULL; + g_set_error(error, CBOX_FLUIDSYNTH_ERROR, CBOX_FLUIDSYNTH_ERROR_FAILED, "Failed to load the SF2 bank %s: %s", bank_name, error_msg); + g_free(error_msg); + return FALSE; + } + m->bank_name = g_strdup(bank_name); + m->sfid = result; + return TRUE; +} + MODULE_CREATE_FUNCTION(fluidsynth) { - int result = 0; int i; const char *bankname = cbox_config_get_string(cfg_section, "sf2"); static int inited = 0; @@ -130,15 +159,19 @@ MODULE_CREATE_FUNCTION(fluidsynth) if (pairs == 0) { CALL_MODULE_INIT(m, 0, 2 * m->output_pairs, fluidsynth); +#if OLD_FLUIDSYNTH m->left_outputs = NULL; m->right_outputs = NULL; +#endif } else { g_message("Multichannel mode enabled, %d output pairs, 2 effects", m->output_pairs); CALL_MODULE_INIT(m, 0, 2 * m->output_pairs + 4, fluidsynth); +#if OLD_FLUIDSYNTH m->left_outputs = malloc(sizeof(float *) * (m->output_pairs + 2)); m->right_outputs = malloc(sizeof(float *) * (m->output_pairs + 2)); +#endif } m->module.process_event = fluidsynth_process_event; m->module.process_block = fluidsynth_process_block; @@ -147,23 +180,23 @@ MODULE_CREATE_FUNCTION(fluidsynth) fluid_settings_setnum(m->settings, "synth.sample-rate", m->module.srate); fluid_settings_setint(m->settings, "synth.audio-channels", m->output_pairs); fluid_settings_setint(m->settings, "synth.audio-groups", m->output_pairs); + fluid_settings_setint(m->settings, "synth.reverb.active", cbox_config_get_int(cfg_section, "reverb", 1)); + fluid_settings_setint(m->settings, "synth.chorus.active", cbox_config_get_int(cfg_section, "chorus", 1)); m->synth = new_fluid_synth(m->settings); - fluid_synth_set_reverb_on(m->synth, cbox_config_get_int(cfg_section, "reverb", 1)); - fluid_synth_set_chorus_on(m->synth, cbox_config_get_int(cfg_section, "chorus", 1)); - + fluid_set_log_function(FLUID_PANIC, cbox_fluidsynth_log_write, m); + fluid_set_log_function(FLUID_ERR, cbox_fluidsynth_log_write, m); + fluid_set_log_function(FLUID_WARN, cbox_fluidsynth_log_write, m); + //fluid_synth_add_sfloader(m->synth, new_fluid_defsfloader(m->settings)); + m->error_log = NULL; m->bank_name = NULL; m->sfid = -1; if (bankname) { - m->bank_name = g_strdup(bankname); - g_message("Loading soundfont %s", bankname); - result = fluid_synth_sfload(m->synth, bankname, 1); - if (result == FLUID_FAILED) + if (!load_soundfont(m, bankname, error)) { - g_set_error(error, CBOX_FLUIDSYNTH_ERROR, CBOX_FLUIDSYNTH_ERROR_FAILED, "Failed to load the default bank %s: %s", bankname, fluid_synth_error(m->synth)); + CBOX_DELETE(&m->module); return NULL; } - m->sfid = result; g_message("Soundfont %s loaded", bankname); } if (bankname) @@ -195,13 +228,19 @@ void fluidsynth_process_block(struct cbox_module *module, cbox_sample_t **inputs fluid_synth_write_float(m->synth, CBOX_BLOCK_SIZE, outputs[0], 0, 1, outputs[1], 0, 1); else { +#if OLD_FLUIDSYNTH for (int i = 0; i < 2 + m->output_pairs; i++) { m->left_outputs[i] = outputs[2 * i]; m->right_outputs[i] = outputs[2 * i + 1]; } - fluid_synth_nwrite_float(m->synth, CBOX_BLOCK_SIZE, m->left_outputs, m->right_outputs, m->left_outputs + m->output_pairs, m->right_outputs + m->output_pairs); +#else + float *fx_outputs[4]; + for (int i = 0; i < 4; i++) + fx_outputs[i] = outputs[2 * m->output_pairs + i]; + fluid_synth_process(m->synth, CBOX_BLOCK_SIZE, 2, fx_outputs, m->output_pairs, outputs); +#endif } } @@ -254,20 +293,15 @@ gboolean fluidsynth_process_load_patch(struct fluidsynth_module *m, const char * char *old_bank_name = m->bank_name; if (bank_name) { - int result = fluid_synth_sfload(m->synth, bank_name, 1); - if (result == FLUID_FAILED) - { - g_set_error(error, CBOX_FLUIDSYNTH_ERROR, CBOX_FLUIDSYNTH_ERROR_FAILED, "Failed to load the bank %s: %s", bank_name, fluid_synth_error(m->synth)); + if (!load_soundfont(m, bank_name, error)) return FALSE; - } - g_message("Soundfont %s loaded at ID %d", bank_name, result); - m->sfid = result; + g_message("Soundfont %s loaded at ID %d", bank_name, m->sfid); } else m->sfid = -1; if (old_sfid != -1) { - free(old_bank_name); + g_free(old_bank_name); fluid_synth_sfunload(m->synth, old_sfid, 1); } if (m->sfid != -1) @@ -359,15 +393,17 @@ void fluidsynth_destroyfunc(struct cbox_module *module) { struct fluidsynth_module *m = (struct fluidsynth_module *)module; +#if OLD_FLUIDSYNTH if (m->output_pairs) { free(m->left_outputs); free(m->right_outputs); } +#endif free(m->bank_name); - delete_fluid_settings(m->settings); delete_fluid_synth(m->synth); + delete_fluid_settings(m->settings); } struct cbox_module_livecontroller_metadata fluidsynth_controllers[] = { diff --git a/template/calfbox/sampler_rll.c b/template/calfbox/sampler_rll.c index 7e8198f..cafc7d2 100644 --- a/template/calfbox/sampler_rll.c +++ b/template/calfbox/sampler_rll.c @@ -10,10 +10,11 @@ static void add_layers(struct sampler_rll *rll, GSList **layers_by_range, struct sampler_layer *l, uint32_t lokey, uint32_t hikey) { if (lokey >= 0 && lokey <= 127 && - hikey >= 0 && hikey <= 127) + hikey >= 0 && hikey <= 127 && lokey <= hikey) { int start = rll->ranges_by_key[lokey]; int end = rll->ranges_by_key[hikey]; + assert(start != 255 && end != 255); for (int i = start; i <= end; ++i) { if (!layers_by_range[i] || layers_by_range[i]->data != l) @@ -86,13 +87,15 @@ struct sampler_rll *sampler_rll_new_from_program(struct sampler_program *prg) uint16_t lo_count[129], hi_count[128], low = 127, high = 0; for (int i = 0; i < 128; i++) lo_count[i] = hi_count[i] = 0; + lo_count[128] = 0; // XXXKF handle 'key' field without relying on the existing ugly hack for (GSList *p = prg->all_layers; p; p = g_slist_next(p)) { struct sampler_layer *l = p->data; if (l->data.lokey >= 0 && l->data.lokey <= 127 && - l->data.hikey >= 0 && l->data.hikey <= 127) + l->data.hikey >= 0 && l->data.hikey <= 127 && + l->data.lokey <= l->data.hikey) { lo_count[l->data.lokey]++; hi_count[l->data.hikey]++;