diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index c530d7ac8..ca401cbd2 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -85,12 +85,11 @@ if(RTMIDI) endif() if(FLUIDSYNTH) - if(APPLE) - find_library(FLUIDSYNTH_LIB fluidsynth) - if (NOT FLUIDSYNTH_LIB) - message(WARNING "Could not find fluid synth. The library will not be bundled and any related features will not work.") - endif() - endif () + find_package(PkgConfig REQUIRED) + pkg_check_modules(FLUIDSYNTH REQUIRED IMPORTED_TARGET fluidsynth) + target_link_libraries(86Box PkgConfig::FLUIDSYNTH) + target_link_libraries(86Box -static ${FLUIDSYNTH_STATIC_LIBRARIES} -fopenmp) + target_compile_definitions(snd PRIVATE USE_FLUIDSYNTH) target_sources(snd PRIVATE midi_fluidsynth.c) endif() diff --git a/src/sound/midi_fluidsynth.c b/src/sound/midi_fluidsynth.c index 2372203d7..4099e043f 100644 --- a/src/sound/midi_fluidsynth.c +++ b/src/sound/midi_fluidsynth.c @@ -8,6 +8,8 @@ # ifdef __unix__ # include # endif +# define FLUIDSYNTH_NOT_A_DLL +# include # include <86box/86box.h> # include <86box/config.h> @@ -28,79 +30,9 @@ # define RENDER_RATE 100 # define BUFFER_SEGMENTS 10 -enum fluid_chorus_mod { - FLUID_CHORUS_MOD_SINE = 0, - FLUID_CHORUS_MOD_TRIANGLE = 1 -}; - -enum fluid_interp { - FLUID_INTERP_NONE = 0, - FLUID_INTERP_LINEAR = 1, - FLUID_INTERP_DEFAULT = 4, - FLUID_INTERP_4THORDER = 4, - FLUID_INTERP_7THORDER = 7, - FLUID_INTERP_HIGHEST = 7 -}; - extern void givealbuffer_midi(void *buf, uint32_t size); extern void al_set_midi(int freq, int buf_size); -static void *fluidsynth_handle; /* handle to FluidSynth DLL */ - -/* Pointers to the real functions. */ -// clang-format off -static void *(*f_new_fluid_settings)(void); -static void (*f_delete_fluid_settings)(void *settings); -static int (*f_fluid_settings_setnum)(void *settings, const char *name, double val); -static int (*f_fluid_settings_getnum)(void *settings, const char *name, double *val); -static void *(*f_new_fluid_synth)(void *settings); -static int (*f_delete_fluid_synth)(void *synth); -static int (*f_fluid_synth_noteon)(void *synth, int chan, int key, int vel); -static int (*f_fluid_synth_noteoff)(void *synth, int chan, int key); -static int (*f_fluid_synth_cc)(void *synth, int chan, int ctrl, int val); -static int (*f_fluid_synth_channel_pressure)(void *synth, int chan, int val); -static int (*f_fluid_synth_sysex)(void *synth, const char *data, int len, char *response, int *response_len, int *handled, int dryrun); -static int (*f_fluid_synth_pitch_bend)(void *synth, int chan, int val); -static int (*f_fluid_synth_program_change)(void *synth, int chan, int program); -static int (*f_fluid_synth_sfload)(void *synth, const char *filename, int reset_presets); -static int (*f_fluid_synth_set_interp_method)(void *synth, int chan, int interp_method); -static void (*f_fluid_synth_set_reverb)(void *synth, double roomsize, double damping, double width, double level); -static void (*f_fluid_synth_set_reverb_on)(void *synth, int on); -static void (*f_fluid_synth_set_chorus)(void *synth, int nr, double level, double speed, double depth_ms, int type); -static void (*f_fluid_synth_set_chorus_on)(void *synth, int on); -static int (*f_fluid_synth_write_s16)(void *synth, int len, void *lout, int loff, int lincr, void *rout, int roff, int rincr); -static int (*f_fluid_synth_write_float)(void *synth, int len, void *lout, int loff, int lincr, void *rout, int roff, int rincr); -static char *(*f_fluid_version_str)(void); -// clang-format on - -static dllimp_t fluidsynth_imports[] = { - // clang-format off - { "new_fluid_settings", &f_new_fluid_settings }, - { "delete_fluid_settings", &f_delete_fluid_settings }, - { "fluid_settings_setnum", &f_fluid_settings_setnum }, - { "fluid_settings_getnum", &f_fluid_settings_getnum }, - { "new_fluid_synth", &f_new_fluid_synth }, - { "delete_fluid_synth", &f_delete_fluid_synth }, - { "fluid_synth_noteon", &f_fluid_synth_noteon }, - { "fluid_synth_noteoff", &f_fluid_synth_noteoff }, - { "fluid_synth_cc", &f_fluid_synth_cc }, - { "fluid_synth_channel_pressure", &f_fluid_synth_channel_pressure }, - { "fluid_synth_sysex", &f_fluid_synth_sysex }, - { "fluid_synth_pitch_bend", &f_fluid_synth_pitch_bend }, - { "fluid_synth_program_change", &f_fluid_synth_program_change }, - { "fluid_synth_sfload", &f_fluid_synth_sfload }, - { "fluid_synth_set_interp_method", &f_fluid_synth_set_interp_method }, - { "fluid_synth_set_reverb", &f_fluid_synth_set_reverb }, - { "fluid_synth_set_reverb_on", &f_fluid_synth_set_reverb_on }, - { "fluid_synth_set_chorus", &f_fluid_synth_set_chorus }, - { "fluid_synth_set_chorus_on", &f_fluid_synth_set_chorus_on }, - { "fluid_synth_write_s16", &f_fluid_synth_write_s16 }, - { "fluid_synth_write_float", &f_fluid_synth_write_float }, - { "fluid_version_str", &f_fluid_version_str }, - { NULL, NULL }, - // clang-format on -}; - typedef struct fluidsynth { void *settings; void *synth; @@ -153,7 +85,7 @@ fluidsynth_thread(void *param) float *buf = (float *) ((uint8_t *) data->buffer + buf_pos); memset(buf, 0, buf_size); if (data->synth) - f_fluid_synth_write_float(data->synth, buf_size / (2 * sizeof(float)), buf, 0, 2, buf, 1, 2); + fluid_synth_write_float(data->synth, buf_size / (2 * sizeof(float)), buf, 0, 2, buf, 1, 2); buf_pos += buf_size; if (buf_pos >= data->buf_size) { givealbuffer_midi(data->buffer, data->buf_size / sizeof(float)); @@ -163,7 +95,7 @@ fluidsynth_thread(void *param) int16_t *buf = (int16_t *) ((uint8_t *) data->buffer_int16 + buf_pos); memset(buf, 0, buf_size); if (data->synth) - f_fluid_synth_write_s16(data->synth, buf_size / (2 * sizeof(int16_t)), buf, 0, 2, buf, 1, 2); + fluid_synth_write_s16(data->synth, buf_size / (2 * sizeof(int16_t)), buf, 0, 2, buf, 1, 2); buf_pos += buf_size; if (buf_pos >= data->buf_size) { givealbuffer_midi(data->buffer_int16, data->buf_size / sizeof(int16_t)); @@ -187,24 +119,24 @@ fluidsynth_msg(uint8_t *msg) switch (cmd) { case 0x80: /* Note Off */ - f_fluid_synth_noteoff(data->synth, chan, param1); + fluid_synth_noteoff(data->synth, chan, param1); break; case 0x90: /* Note On */ - f_fluid_synth_noteon(data->synth, chan, param1, param2); + fluid_synth_noteon(data->synth, chan, param1, param2); break; case 0xA0: /* Aftertouch */ break; case 0xB0: /* Control Change */ - f_fluid_synth_cc(data->synth, chan, param1, param2); + fluid_synth_cc(data->synth, chan, param1, param2); break; case 0xC0: /* Program Change */ - f_fluid_synth_program_change(data->synth, chan, param1); + fluid_synth_program_change(data->synth, chan, param1); break; case 0xD0: /* Channel Pressure */ - f_fluid_synth_channel_pressure(data->synth, chan, param1); + fluid_synth_channel_pressure(data->synth, chan, param1); break; case 0xE0: /* Pitch Bend */ - f_fluid_synth_pitch_bend(data->synth, chan, (param2 << 7) | param1); + fluid_synth_pitch_bend(data->synth, chan, (param2 << 7) | param1); break; case 0xF0: /* SysEx */ break; @@ -218,7 +150,7 @@ fluidsynth_sysex(uint8_t *data, unsigned int len) { fluidsynth_t *d = &fsdev; - f_fluid_synth_sysex(d->synth, (const char *) data, len, 0, 0, 0, 0); + fluid_synth_sysex(d->synth, (const char *) data, len, 0, 0, 0, 0); } void * @@ -229,31 +161,12 @@ fluidsynth_init(const device_t *info) memset(data, 0, sizeof(fluidsynth_t)); - /* Try loading the DLL. */ -# ifdef _WIN32 -# if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) - fluidsynth_handle = dynld_module("libfluidsynth.dll", fluidsynth_imports); -# else - fluidsynth_handle = dynld_module("libfluidsynth64.dll", fluidsynth_imports); -# endif -# elif defined __APPLE__ - fluidsynth_handle = dynld_module("libfluidsynth.dylib", fluidsynth_imports); -# else - fluidsynth_handle = dynld_module("libfluidsynth.so.3", fluidsynth_imports); - if (fluidsynth_handle == NULL) - fluidsynth_handle = dynld_module("libfluidsynth.so.2", fluidsynth_imports); -# endif - if (fluidsynth_handle == NULL) { - ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2080, (wchar_t *) IDS_2134); - return NULL; - } + data->settings = new_fluid_settings(); - data->settings = f_new_fluid_settings(); + fluid_settings_setnum(data->settings, "synth.sample-rate", 44100); + fluid_settings_setnum(data->settings, "synth.gain", device_get_config_int("output_gain") / 100.0f); - f_fluid_settings_setnum(data->settings, "synth.sample-rate", 44100); - f_fluid_settings_setnum(data->settings, "synth.gain", device_get_config_int("output_gain") / 100.0f); - - data->synth = f_new_fluid_synth(data->settings); + data->synth = new_fluid_synth(data->settings); const char *sound_font = (char *) device_get_config_string("sound_font"); # ifdef __unix__ @@ -261,10 +174,10 @@ fluidsynth_init(const device_t *info) sound_font = (access("/usr/share/sounds/sf2/FluidR3_GM.sf2", F_OK) == 0 ? "/usr/share/sounds/sf2/FluidR3_GM.sf2" : (access("/usr/share/soundfonts/default.sf2", F_OK) == 0 ? "/usr/share/soundfonts/default.sf2" : "")); # endif - data->sound_font = f_fluid_synth_sfload(data->synth, sound_font, 1); + data->sound_font = fluid_synth_sfload(data->synth, sound_font, 1); if (device_get_config_int("chorus")) { - f_fluid_synth_set_chorus_on(data->synth, 1); + fluid_synth_set_chorus_on(data->synth, 1); int chorus_voices = device_get_config_int("chorus_voices"); double chorus_level = device_get_config_int("chorus_level") / 100.0; @@ -277,21 +190,21 @@ fluidsynth_init(const device_t *info) else chorus_waveform = FLUID_CHORUS_MOD_TRIANGLE; - f_fluid_synth_set_chorus(data->synth, chorus_voices, chorus_level, chorus_speed, chorus_depth, chorus_waveform); + fluid_synth_set_chorus(data->synth, chorus_voices, chorus_level, chorus_speed, chorus_depth, chorus_waveform); } else - f_fluid_synth_set_chorus_on(data->synth, 0); + fluid_synth_set_chorus_on(data->synth, 0); if (device_get_config_int("reverb")) { - f_fluid_synth_set_reverb_on(data->synth, 1); + fluid_synth_set_reverb_on(data->synth, 1); double reverb_room_size = device_get_config_int("reverb_room_size") / 100.0; double reverb_damping = device_get_config_int("reverb_damping") / 100.0; int reverb_width = device_get_config_int("reverb_width"); double reverb_level = device_get_config_int("reverb_level") / 100.0; - f_fluid_synth_set_reverb(data->synth, reverb_room_size, reverb_damping, reverb_width, reverb_level); + fluid_synth_set_reverb(data->synth, reverb_room_size, reverb_damping, reverb_width, reverb_level); } else - f_fluid_synth_set_reverb_on(data->synth, 0); + fluid_synth_set_reverb_on(data->synth, 0); int interpolation = device_get_config_int("interpolation"); int fs_interpolation = FLUID_INTERP_4THORDER; @@ -305,10 +218,10 @@ fluidsynth_init(const device_t *info) else if (interpolation == 3) fs_interpolation = FLUID_INTERP_7THORDER; - f_fluid_synth_set_interp_method(data->synth, -1, fs_interpolation); + fluid_synth_set_interp_method(data->synth, -1, fs_interpolation); double samplerate; - f_fluid_settings_getnum(data->settings, "synth.sample-rate", &samplerate); + fluid_settings_getnum(data->settings, "synth.sample-rate", &samplerate); data->samplerate = (int) samplerate; if (sound_is_float) { data->buf_size = (data->samplerate / RENDER_RATE) * 2 * sizeof(float) * BUFFER_SEGMENTS; @@ -357,12 +270,12 @@ fluidsynth_close(void *p) thread_wait(data->thread_h); if (data->synth) { - f_delete_fluid_synth(data->synth); + delete_fluid_synth(data->synth); data->synth = NULL; } if (data->settings) { - f_delete_fluid_settings(data->settings); + delete_fluid_settings(data->settings); data->settings = NULL; } @@ -375,12 +288,6 @@ fluidsynth_close(void *p) free(data->buffer_int16); data->buffer_int16 = NULL; } - - /* Unload the DLL if possible. */ - if (fluidsynth_handle != NULL) { - dynld_close(fluidsynth_handle); - fluidsynth_handle = NULL; - } } static const device_config_t fluidsynth_config[] = {