From 27190c5ee55726dfa3ecdeda4d7755d436ec1caa Mon Sep 17 00:00:00 2001 From: jet2jet <34238471+jet2jet@users.noreply.github.com> Date: Tue, 27 Dec 2022 22:55:54 +0900 Subject: [PATCH 1/9] [fluidsynth-emscripten] patch for build with Emscripten (for v2.3.x) --- CMakeLists.txt | 90 ++++++++- doc/examples/CMakeLists.txt | 24 ++- emscripten/exports.txt | 367 ++++++++++++++++++++++++++++++++++++ emscripten/make-exports.js | 88 +++++++++ emscripten/src/pre.js | 13 ++ include/fluidsynth.cmake | 7 + src/CMakeLists.txt | 43 ++++- src/utils/fluid_settings.c | 4 + src/utils/fluid_sys.c | 21 +++ src/utils/fluid_sys.h | 253 ++++++++++++++++++++++++- src/utils/fluidsynth_priv.h | 26 ++- 11 files changed, 919 insertions(+), 17 deletions(-) create mode 100644 emscripten/exports.txt create mode 100644 emscripten/make-exports.js create mode 100644 emscripten/src/pre.js diff --git a/CMakeLists.txt b/CMakeLists.txt index 051aad734..dcdaf7b20 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,9 @@ endif() project ( FluidSynth C CXX ) list( APPEND CMAKE_MODULE_PATH ${FluidSynth_SOURCE_DIR}/cmake_admin ) +if ( CMAKE_SYSTEM_NAME MATCHES "Emscripten" ) + list (APPEND CMAKE_MODULE_PATH "${EMSCRIPTEN_ROOT_PATH}/cmake/Modules" ) +endif ( CMAKE_SYSTEM_NAME MATCHES "Emscripten" ) # FluidSynth package name set ( PACKAGE "fluidsynth" ) @@ -115,6 +118,15 @@ if ( CMAKE_SYSTEM MATCHES "OS2" ) set ( enable-ipv6 off ) endif ( CMAKE_SYSTEM MATCHES "OS2" ) +unset ( EMSCRIPTEN_SUPPORT CACHE ) +if ( CMAKE_SYSTEM_NAME MATCHES "Emscripten" ) + option ( enable-separate-wasm "generate separate .wasm file" off ) + set ( EMSCRIPTEN_SUPPORT on ) + set ( enable-network off ) + set ( enable-readline off ) + set ( enable-threads off ) +endif ( CMAKE_SYSTEM_NAME MATCHES "Emscripten" ) + # the default C standard to use for all targets set(CMAKE_C_STANDARD 90) @@ -192,8 +204,10 @@ unset ( ENABLE_UBSAN CACHE ) if ( CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "Intel" ) if ( NOT APPLE AND NOT OS2 AND NOT EMSCRIPTEN ) - set ( CMAKE_EXE_LINKER_FLAGS - "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed" ) + if ( NOT EMSCRIPTEN_SUPPORT ) + set ( CMAKE_EXE_LINKER_FLAGS + "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed" ) + endif ( NOT EMSCRIPTEN_SUPPORT ) set ( CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined" ) endif ( NOT APPLE AND NOT OS2 AND NOT EMSCRIPTEN ) @@ -208,7 +222,11 @@ if ( CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_C_C set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -W -Wpointer-arith -Wcast-qual -Wno-unused-parameter" ) # prepend to build type specific flags, to allow users to override - set ( CMAKE_C_FLAGS_DEBUG "-g ${CMAKE_C_FLAGS_DEBUG}" ) + if ( EMSCRIPTEN_SUPPORT ) + set ( CMAKE_C_FLAGS_DEBUG "-g4 ${CMAKE_C_FLAGS_DEBUG}" ) + else ( EMSCRIPTEN_SUPPORT ) + set ( CMAKE_C_FLAGS_DEBUG "-g ${CMAKE_C_FLAGS_DEBUG}" ) + endif ( EMSCRIPTEN_SUPPORT ) if ( CMAKE_C_COMPILER_ID STREQUAL "Intel" ) # icc needs the restrict flag to recognize C99 restrict pointers @@ -475,6 +493,9 @@ if ( ASTYLE ) ) endif(ASTYLE) +include ( PkgConfigHelpers ) # has unset_pkg_config() + +if(NOT EMSCRIPTEN_SUPPORT) find_package ( PkgConfig REQUIRED ) # Mandatory libraries: glib and gthread @@ -485,8 +506,6 @@ if ( GLIB_glib-2.0_VERSION AND GLIB_glib-2.0_VERSION VERSION_LESS "2.26.0" ) message ( WARNING "Your version of glib is very old. This may cause problems with fluidsynth's sample cache on Windows. Consider updating to glib 2.26 or newer!" ) endif ( GLIB_glib-2.0_VERSION AND GLIB_glib-2.0_VERSION VERSION_LESS "2.26.0" ) -include ( PkgConfigHelpers ) # has unset_pkg_config() - # Optional features unset ( LIBSNDFILE_SUPPORT CACHE ) unset ( LIBSNDFILE_HASVORBIS CACHE ) @@ -677,6 +696,67 @@ if ( READLINE_FOUND ) endif ( READLINE_FOUND ) endif ( enable-readline ) +else (NOT EMSCRIPTEN_SUPPORT) + FILE( STRINGS "emscripten/exports.txt" EMSCRIPTEN_EXPORTS_OPTIONS NEWLINE_CONSUME ) + STRING ( REPLACE "\n" "" EMSCRIPTEN_EXPORTS_OPTIONS "${EMSCRIPTEN_EXPORTS_OPTIONS}" ) + if ( NOT BUILD_SHARED_LIBS ) + SET( EMSCRIPTEN_EXPORTS_OPTIONS "${EMSCRIPTEN_EXPORTS_OPTIONS}\"_main\"," ) + endif ( NOT BUILD_SHARED_LIBS ) + STRING ( REGEX REPLACE ",$" "" EMSCRIPTEN_EXPORTS_OPTIONS "${EMSCRIPTEN_EXPORTS_OPTIONS}" ) + SET( NO_GLIB 1 ) + SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNO_GLIB -DFLUIDSYNTH_DLL_EXPORTS" ) + if ( NOT enable-separate-wasm ) + SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s SINGLE_FILE=1" ) + endif ( NOT enable-separate-wasm ) + SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --pre-js ${CMAKE_SOURCE_DIR}/emscripten/src/pre.js -s ENVIRONMENT=web -s INITIAL_MEMORY=67108864 -s ALLOW_MEMORY_GROWTH=1 -s ALLOW_TABLE_GROWTH=1 -s EXPORTED_FUNCTIONS='[${EMSCRIPTEN_EXPORTS_OPTIONS}]' -s 'EXTRA_EXPORTED_RUNTIME_METHODS=[\"ccall\", \"cwrap\", \"FS\"]'" ) + SET( CMAKE_EXECUTABLE_SUFFIX ".js" ) + + find_package ( PkgConfig REQUIRED ) + + # Optional features + unset ( LIBSNDFILE_SUPPORT CACHE ) + unset ( LIBSNDFILE_HASVORBIS CACHE ) + if ( enable-libsndfile ) + pkg_check_modules ( LIBSNDFILE sndfile>=1.0.0 IMPORTED_TARGET ) + set ( LIBSNDFILE_SUPPORT ${LIBSNDFILE_FOUND} ) + if ( LIBSNDFILE_SUPPORT ) + # Patch to use 'opus' + if ( NOT LIBSNDFILE_STATIC_LIBRARIES MATCHES "opus" ) + list ( APPEND LIBSNDFILE_STATIC_LIBRARIES "opus" ) + list ( APPEND LIBSNDFILE_STATIC_LDFLAGS "-lopus" ) + endif () + if ( NOT LIBSNDFILE_STATIC_LIBRARY_DIRS ) + set ( LIBSNDFILE_STATIC_LIBRARY_DIRS "${CMAKE_INSTALL_PREFIX}/lib" ) + endif () + #[[ cmake_print_variables ( + LIBSNDFILE_STATIC_LIBRARIES + LIBSNDFILE_STATIC_LINK_LIBRARIES + LIBSNDFILE_STATIC_LDFLAGS + LIBSNDFILE_STATIC_LIBRARY_DIRS + LIBSNDFILE_STATIC_LDFLAGS_OTHER ) ]] + list( APPEND PC_REQUIRES_PRIV "sndfile") + if ( LIBSNDFILE_STATIC_LIBRARIES MATCHES "vorbis" OR + LIBSNDFILE_STATIC_LDFLAGS MATCHES "vorbis" OR + LIBSNDFILE_STATIC_LDFLAGS_OTHER MATCHES "vorbis" ) + set ( LIBSNDFILE_HASVORBIS 1 ) + else () + message ( NOTICE "Seems like libsndfile was compiled without OGG/Vorbis support." ) + endif () + #[[ cmake_print_properties( TARGETS PkgConfig::LIBSNDFILE + PROPERTIES + INTERFACE_COMPILE_OPTIONS + INTERFACE_INCLUDE_DIRECTORIES + INTERFACE_LINK_OPTIONS + INTERFACE_LINK_LIBRARIES ) ]] + sanitize_target_dirs(PkgConfig::LIBSNDFILE) + endif ( LIBSNDFILE_SUPPORT ) + else ( enable-libsndfile ) + unset_pkg_config ( LIBSNDFILE ) + unset_pkg_config ( LIBSNDFILE_VORBIS ) + endif ( enable-libsndfile ) + +endif (NOT EMSCRIPTEN_SUPPORT) + unset ( AUFILE_SUPPORT CACHE ) if ( enable-aufile ) set ( AUFILE_SUPPORT 1 ) diff --git a/doc/examples/CMakeLists.txt b/doc/examples/CMakeLists.txt index ec75a5218..47dbde6d8 100644 --- a/doc/examples/CMakeLists.txt +++ b/doc/examples/CMakeLists.txt @@ -19,12 +19,22 @@ # CMake based build system. Pedro Lopez-Cabanillas -include ( FluidUnitTest ) -add_custom_target ( demo ) +unset ( BUILD_DEMOS ) +if ( NOT EMSCRIPTEN_SUPPORT ) + set ( BUILD_DEMOS on ) +elseif ( NOT BUILD_SHARED_LIBS ) + set ( BUILD_DEMOS on ) +else ( NOT EMSCRIPTEN_SUPPORT ) + set ( BUILD_DEMOS off ) +endif ( NOT EMSCRIPTEN_SUPPORT ) -ADD_FLUID_DEMO ( example ) -ADD_FLUID_DEMO ( fluidsynth_arpeggio ) -ADD_FLUID_DEMO ( fluidsynth_fx ) -ADD_FLUID_DEMO ( fluidsynth_metronome ) -ADD_FLUID_DEMO ( fluidsynth_simple ) +if ( BUILD_DEMOS ) + include ( FluidUnitTest ) + add_custom_target ( demo ) + ADD_FLUID_DEMO ( example ) + ADD_FLUID_DEMO ( fluidsynth_arpeggio ) + ADD_FLUID_DEMO ( fluidsynth_fx ) + ADD_FLUID_DEMO ( fluidsynth_metronome ) + ADD_FLUID_DEMO ( fluidsynth_simple ) +endif ( BUILD_DEMOS ) diff --git a/emscripten/exports.txt b/emscripten/exports.txt new file mode 100644 index 000000000..7def4418c --- /dev/null +++ b/emscripten/exports.txt @@ -0,0 +1,367 @@ +"_malloc", +"_free", +"_fluid_voice_add_mod", +"_fluid_voice_gen_get", +"_fluid_voice_gen_set", +"_fluid_voice_gen_incr", +"_fluid_voice_get_id", +"_fluid_voice_get_channel", +"_fluid_voice_get_key", +"_fluid_voice_get_actual_key", +"_fluid_voice_get_velocity", +"_fluid_voice_get_actual_velocity", +"_fluid_voice_is_playing", +"_fluid_voice_is_on", +"_fluid_voice_is_sustained", +"_fluid_voice_is_sostenuto", +"_fluid_voice_optimize_sample", +"_fluid_voice_update_param", +"_fluid_version", +"_fluid_version_str", +"_new_fluid_synth", +"_delete_fluid_synth", +"_fluid_synth_get_cpu_load", +"_fluid_synth_error", +"_fluid_synth_noteon", +"_fluid_synth_noteoff", +"_fluid_synth_cc", +"_fluid_synth_get_cc", +"_fluid_synth_sysex", +"_fluid_synth_pitch_bend", +"_fluid_synth_get_pitch_bend", +"_fluid_synth_pitch_wheel_sens", +"_fluid_synth_get_pitch_wheel_sens", +"_fluid_synth_program_change", +"_fluid_synth_channel_pressure", +"_fluid_synth_key_pressure", +"_fluid_synth_bank_select", +"_fluid_synth_sfont_select", +"_fluid_synth_program_select", +"_fluid_synth_program_select_by_sfont_name", +"_fluid_synth_get_program", +"_fluid_synth_unset_program", +"_fluid_synth_program_reset", +"_fluid_synth_system_reset", +"_fluid_synth_all_notes_off", +"_fluid_synth_all_sounds_off", +"_fluid_synth_set_gen", +"_fluid_synth_get_gen", +"_fluid_synth_start", +"_fluid_synth_stop", +"_fluid_synth_alloc_voice", +"_fluid_synth_start_voice", +"_fluid_synth_get_voicelist", +"_fluid_synth_sfload", +"_fluid_synth_sfreload", +"_fluid_synth_sfunload", +"_fluid_synth_add_sfont", +"_fluid_synth_remove_sfont", +"_fluid_synth_sfcount", +"_fluid_synth_get_sfont", +"_fluid_synth_get_sfont_by_id", +"_fluid_synth_get_sfont_by_name", +"_fluid_synth_set_bank_offset", +"_fluid_synth_get_bank_offset", +"_fluid_synth_set_reverb_on", +"_fluid_synth_reverb_on", +"_fluid_synth_set_reverb", +"_fluid_synth_set_reverb_roomsize", +"_fluid_synth_set_reverb_damp", +"_fluid_synth_set_reverb_width", +"_fluid_synth_set_reverb_level", +"_fluid_synth_get_reverb_roomsize", +"_fluid_synth_get_reverb_damp", +"_fluid_synth_get_reverb_level", +"_fluid_synth_get_reverb_width", +"_fluid_synth_set_reverb_group_roomsize", +"_fluid_synth_set_reverb_group_damp", +"_fluid_synth_set_reverb_group_width", +"_fluid_synth_set_reverb_group_level", +"_fluid_synth_get_reverb_group_roomsize", +"_fluid_synth_get_reverb_group_damp", +"_fluid_synth_get_reverb_group_width", +"_fluid_synth_get_reverb_group_level", +"_fluid_synth_set_chorus_on", +"_fluid_synth_chorus_on", +"_fluid_synth_set_chorus", +"_fluid_synth_set_chorus_nr", +"_fluid_synth_set_chorus_level", +"_fluid_synth_set_chorus_speed", +"_fluid_synth_set_chorus_depth", +"_fluid_synth_set_chorus_type", +"_fluid_synth_get_chorus_nr", +"_fluid_synth_get_chorus_level", +"_fluid_synth_get_chorus_speed", +"_fluid_synth_get_chorus_depth", +"_fluid_synth_get_chorus_type", +"_fluid_synth_set_chorus_group_nr", +"_fluid_synth_set_chorus_group_level", +"_fluid_synth_set_chorus_group_speed", +"_fluid_synth_set_chorus_group_depth", +"_fluid_synth_set_chorus_group_type", +"_fluid_synth_get_chorus_group_nr", +"_fluid_synth_get_chorus_group_level", +"_fluid_synth_get_chorus_group_speed", +"_fluid_synth_get_chorus_group_depth", +"_fluid_synth_get_chorus_group_type", +"_fluid_synth_count_midi_channels", +"_fluid_synth_count_audio_channels", +"_fluid_synth_count_audio_groups", +"_fluid_synth_count_effects_channels", +"_fluid_synth_count_effects_groups", +"_fluid_synth_set_sample_rate", +"_fluid_synth_set_gain", +"_fluid_synth_get_gain", +"_fluid_synth_set_polyphony", +"_fluid_synth_get_polyphony", +"_fluid_synth_get_active_voice_count", +"_fluid_synth_get_internal_bufsize", +"_fluid_synth_set_interp_method", +"_fluid_synth_add_default_mod", +"_fluid_synth_remove_default_mod", +"_fluid_synth_activate_key_tuning", +"_fluid_synth_activate_octave_tuning", +"_fluid_synth_tune_notes", +"_fluid_synth_activate_tuning", +"_fluid_synth_deactivate_tuning", +"_fluid_synth_tuning_iteration_start", +"_fluid_synth_tuning_iteration_next", +"_fluid_synth_tuning_dump", +"_fluid_synth_write_s16", +"_fluid_synth_write_float", +"_fluid_synth_nwrite_float", +"_fluid_synth_process", +"_fluid_synth_set_custom_filter", +"_fluid_synth_set_channel_type", +"_fluid_synth_reset_basic_channel", +"_fluid_synth_get_basic_channel", +"_fluid_synth_set_basic_channel", +"_fluid_synth_set_legato_mode", +"_fluid_synth_get_legato_mode", +"_fluid_synth_set_portamento_mode", +"_fluid_synth_get_portamento_mode", +"_fluid_synth_set_breath_mode", +"_fluid_synth_get_breath_mode", +"_fluid_synth_get_settings", +"_fluid_synth_add_sfloader", +"_fluid_synth_get_channel_preset", +"_fluid_synth_handle_midi_event", +"_fluid_synth_pin_preset", +"_fluid_synth_unpin_preset", +"_fluid_synth_get_ladspa_fx", +"_new_fluid_sfloader", +"_delete_fluid_sfloader", +"_new_fluid_defsfloader", +"_fluid_sfloader_set_callbacks", +"_fluid_sfloader_set_data", +"_fluid_sfloader_get_data", +"_new_fluid_sfont", +"_delete_fluid_sfont", +"_fluid_sfont_set_data", +"_fluid_sfont_get_data", +"_fluid_sfont_get_id", +"_fluid_sfont_get_name", +"_fluid_sfont_get_preset", +"_fluid_sfont_iteration_start", +"_fluid_sfont_iteration_next", +"_new_fluid_preset", +"_delete_fluid_preset", +"_fluid_preset_set_data", +"_fluid_preset_get_data", +"_fluid_preset_get_name", +"_fluid_preset_get_banknum", +"_fluid_preset_get_num", +"_fluid_preset_get_sfont", +"_new_fluid_sample", +"_delete_fluid_sample", +"_fluid_sample_sizeof", +"_fluid_sample_set_name", +"_fluid_sample_set_sound_data", +"_fluid_sample_set_loop", +"_fluid_sample_set_pitch", +"_new_fluid_settings", +"_delete_fluid_settings", +"_fluid_settings_get_type", +"_fluid_settings_get_hints", +"_fluid_settings_is_realtime", +"_fluid_settings_setstr", +"_fluid_settings_copystr", +"_fluid_settings_dupstr", +"_fluid_settings_getstr_default", +"_fluid_settings_str_equal", +"_fluid_settings_setnum", +"_fluid_settings_getnum", +"_fluid_settings_getnum_default", +"_fluid_settings_getnum_range", +"_fluid_settings_setint", +"_fluid_settings_getint", +"_fluid_settings_getint_default", +"_fluid_settings_getint_range", +"_fluid_settings_foreach_option", +"_fluid_settings_option_count", +"_fluid_settings_option_concat", +"_fluid_settings_foreach", +"_fluid_sequencer_register_fluidsynth", +"_fluid_sequencer_add_midi_event_to_buffer", +"_new_fluid_sequencer", +"_new_fluid_sequencer2", +"_delete_fluid_sequencer", +"_fluid_sequencer_get_use_system_timer", +"_fluid_sequencer_register_client", +"_fluid_sequencer_unregister_client", +"_fluid_sequencer_count_clients", +"_fluid_sequencer_get_client_id", +"_fluid_sequencer_get_client_name", +"_fluid_sequencer_client_is_dest", +"_fluid_sequencer_process", +"_fluid_sequencer_send_now", +"_fluid_sequencer_send_at", +"_fluid_sequencer_remove_events", +"_fluid_sequencer_get_tick", +"_fluid_sequencer_set_time_scale", +"_fluid_sequencer_get_time_scale", +"_new_fluid_mod", +"_delete_fluid_mod", +"_fluid_mod_sizeof", +"_fluid_mod_set_source1", +"_fluid_mod_set_source2", +"_fluid_mod_set_dest", +"_fluid_mod_set_amount", +"_fluid_mod_get_source1", +"_fluid_mod_get_flags1", +"_fluid_mod_get_source2", +"_fluid_mod_get_flags2", +"_fluid_mod_get_dest", +"_fluid_mod_get_amount", +"_fluid_mod_test_identity", +"_fluid_mod_has_source", +"_fluid_mod_has_dest", +"_fluid_mod_clone", +"_fluid_is_soundfont", +"_fluid_is_midifile", +"_fluid_free", +"_new_fluid_midi_event", +"_delete_fluid_midi_event", +"_fluid_midi_event_set_type", +"_fluid_midi_event_get_type", +"_fluid_midi_event_set_channel", +"_fluid_midi_event_get_channel", +"_fluid_midi_event_get_key", +"_fluid_midi_event_set_key", +"_fluid_midi_event_get_velocity", +"_fluid_midi_event_set_velocity", +"_fluid_midi_event_get_control", +"_fluid_midi_event_set_control", +"_fluid_midi_event_get_value", +"_fluid_midi_event_set_value", +"_fluid_midi_event_get_program", +"_fluid_midi_event_set_program", +"_fluid_midi_event_get_pitch", +"_fluid_midi_event_set_pitch", +"_fluid_midi_event_set_sysex", +"_fluid_midi_event_set_text", +"_fluid_midi_event_get_text", +"_fluid_midi_event_set_lyrics", +"_fluid_midi_event_get_lyrics", +"_new_fluid_midi_router", +"_delete_fluid_midi_router", +"_fluid_midi_router_set_default_rules", +"_fluid_midi_router_clear_rules", +"_fluid_midi_router_add_rule", +"_new_fluid_midi_router_rule", +"_delete_fluid_midi_router_rule", +"_fluid_midi_router_rule_set_chan", +"_fluid_midi_router_rule_set_param1", +"_fluid_midi_router_rule_set_param2", +"_fluid_midi_router_handle_midi_event", +"_fluid_midi_dump_prerouter", +"_fluid_midi_dump_postrouter", +"_new_fluid_midi_driver", +"_delete_fluid_midi_driver", +"_new_fluid_player", +"_delete_fluid_player", +"_fluid_player_add", +"_fluid_player_add_mem", +"_fluid_player_play", +"_fluid_player_stop", +"_fluid_player_join", +"_fluid_player_set_loop", +"_fluid_player_set_tempo", +"_fluid_player_set_midi_tempo", +"_fluid_player_set_bpm", +"_fluid_player_set_playback_callback", +"_fluid_player_set_tick_callback", +"_fluid_player_get_status", +"_fluid_player_get_current_tick", +"_fluid_player_get_total_ticks", +"_fluid_player_get_bpm", +"_fluid_player_get_midi_tempo", +"_fluid_player_seek", +"_fluid_set_log_function", +"_fluid_default_log_function", +"_fluid_log", +"_fluid_ladspa_is_active", +"_fluid_ladspa_activate", +"_fluid_ladspa_deactivate", +"_fluid_ladspa_reset", +"_fluid_ladspa_check", +"_fluid_ladspa_host_port_exists", +"_fluid_ladspa_add_buffer", +"_fluid_ladspa_buffer_exists", +"_fluid_ladspa_add_effect", +"_fluid_ladspa_effect_can_mix", +"_fluid_ladspa_effect_set_mix", +"_fluid_ladspa_effect_port_exists", +"_fluid_ladspa_effect_set_control", +"_fluid_ladspa_effect_link", +"_new_fluid_event", +"_delete_fluid_event", +"_fluid_event_set_source", +"_fluid_event_set_dest", +"_fluid_event_timer", +"_fluid_event_note", +"_fluid_event_noteon", +"_fluid_event_noteoff", +"_fluid_event_all_sounds_off", +"_fluid_event_all_notes_off", +"_fluid_event_bank_select", +"_fluid_event_program_change", +"_fluid_event_program_select", +"_fluid_event_control_change", +"_fluid_event_pitch_bend", +"_fluid_event_pitch_wheelsens", +"_fluid_event_modulation", +"_fluid_event_sustain", +"_fluid_event_pan", +"_fluid_event_volume", +"_fluid_event_reverb_send", +"_fluid_event_chorus_send", +"_fluid_event_key_pressure", +"_fluid_event_channel_pressure", +"_fluid_event_system_reset", +"_fluid_event_unregistering", +"_fluid_event_scale", +"_fluid_event_from_midi_event", +"_fluid_event_get_type", +"_fluid_event_get_source", +"_fluid_event_get_dest", +"_fluid_event_get_channel", +"_fluid_event_get_key", +"_fluid_event_get_velocity", +"_fluid_event_get_control", +"_fluid_event_get_value", +"_fluid_event_get_program", +"_fluid_event_get_data", +"_fluid_event_get_duration", +"_fluid_event_get_bank", +"_fluid_event_get_pitch", +"_fluid_event_get_scale", +"_fluid_event_get_sfont_id", +"_new_fluid_audio_driver", +"_new_fluid_audio_driver2", +"_delete_fluid_audio_driver", +"_fluid_audio_driver_register", +"_new_fluid_file_renderer", +"_delete_fluid_file_renderer", +"_fluid_file_renderer_process_block", +"_fluid_file_set_encoding_quality", diff --git a/emscripten/make-exports.js b/emscripten/make-exports.js new file mode 100644 index 000000000..94ce0a687 --- /dev/null +++ b/emscripten/make-exports.js @@ -0,0 +1,88 @@ +#!node + +const fs = require('fs'); +const path = require('path'); + +const OUTPUT_NAME = path.resolve(__dirname, 'exports.txt'); +const INCLUDE_DIR = path.resolve(__dirname, '../include'); +const IGNORE_FUNCTIONS = [ + 'fluid_seq_gettrace', + 'fluid_seq_cleartrace', +]; + +/** + * @param {String[][]} a + * @return {String[]} + */ +function flattenArray(a) { + return a.reduce((p, c) => c.concat(p), []); +} + +/** + * @param {String} dir + * @param {boolean} [recursive] + * @param {(entry:string, fullName:string)=>boolean} [excludeFn] + * @return {String[]} + */ +function gatherIncludeFiles(dir, recursive, excludeFn) { + const entries = fs.readdirSync(dir, 'utf8'); + /** @type {String[]} */ + let files = []; + /** @type {String[]} */ + let dirs = []; + entries.forEach((entry) => { + const name = path.join(dir, entry); + const st = fs.statSync(name); + if (st.isDirectory()) { + dirs.push(name); + } else { + if (/\.h(?:\.in)?$/.test(entry)) { + if (!excludeFn || !excludeFn(entry, name)) { + files.push(name); + } + } + } + }); + if (recursive) { + files = files.concat( + flattenArray(dirs.map((subDir) => gatherIncludeFiles(subDir, recursive, excludeFn))) + ); + } + return files; +} + +/** + * @param {String} file + * @return {String[]} + */ +function gatherAPIDeclarations(file) { + const lines = fs.readFileSync(file, 'utf8').replace(/\r\n/g, '\n').split(/[\r\n]/g); + /** @type {String[]} */ + const funcs = []; + let cachedLine = ''; + lines.forEach((line) => { + if (/^[ \t]*\#/g.test(line)) { + return; + } + cachedLine += ' ' + line; + while (true) { + const ra = /^(.*)?\;(.*)$/g.exec(cachedLine); + if (!ra) { + break; + } + const targetData = ra[1]; + cachedLine = ra[2]; + const ra2 = /FLUIDSYNTH_API(?:[ \r\n]+?[A-Za-z0-9_\*]+?)+?[ \r\n]+?\*?([A-Za-z0-9_]+)\(/.exec(targetData); + if (ra2) { + funcs.push(ra2[1]); + } + } + }); + return funcs; +} + +const includes = gatherIncludeFiles(INCLUDE_DIR, true, (e) => e === 'shell.h'); +const funcs = flattenArray(includes.map((file) => gatherAPIDeclarations(file))) + .filter((name) => IGNORE_FUNCTIONS.indexOf(name) < 0); + +fs.writeFileSync(OUTPUT_NAME, '"_' + funcs.join('",\n"_') + '",\n'); diff --git a/emscripten/src/pre.js b/emscripten/src/pre.js new file mode 100644 index 000000000..dd6379501 --- /dev/null +++ b/emscripten/src/pre.js @@ -0,0 +1,13 @@ +//var Module = typeof Module !== 'undefined' ? Module : {}; +// (to avoid errors occurred in emscripten's code) +var document = typeof document !== 'undefined' ? document : {}; +var window = typeof window !== 'undefined' ? window : {}; +// expose wasm API to AudioWorklet +if (typeof AudioWorkletGlobalScope !== 'undefined' && AudioWorkletGlobalScope) { + AudioWorkletGlobalScope.wasmModule = Module; + AudioWorkletGlobalScope.wasmAddFunction = addFunction; + AudioWorkletGlobalScope.wasmRemoveFunction = removeFunction; + AudioWorkletGlobalScope.addOnPreRun = addOnPreRun; + AudioWorkletGlobalScope.addOnInit = addOnInit; + AudioWorkletGlobalScope.addOnPostRun = addOnPostRun; +} diff --git a/include/fluidsynth.cmake b/include/fluidsynth.cmake index 654a4fd17..00941b8ad 100644 --- a/include/fluidsynth.cmake +++ b/include/fluidsynth.cmake @@ -49,6 +49,13 @@ extern "C" { #elif defined(__GNUC__) #define FLUIDSYNTH_API __attribute__ ((visibility ("default"))) +#elif defined(__EMSCRIPTEN__) +#if defined(FLUIDSYNTH_DLL_EXPORTS) +#include +#define FLUIDSYNTH_API EMSCRIPTEN_KEEPALIVE +#else +#define FLUIDSYNTH_API +#endif #else #define FLUIDSYNTH_API diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e86a6429c..7c19a58af 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -108,6 +108,10 @@ endif ( OBOE_SUPPORT ) set ( config_SOURCES ${FluidSynth_BINARY_DIR}/config.h ) +if ( NOT EMSCRIPTEN_SUPPORT ) + set ( fluid_shell_SOURCES bindings/fluid_cmd.c bindings/fluid_cmd.h ) +endif ( NOT EMSCRIPTEN_SUPPORT ) + set ( libfluidsynth_SOURCES utils/fluid_conv.c utils/fluid_conv.h @@ -175,8 +179,6 @@ set ( libfluidsynth_SOURCES drivers/fluid_adriver.h drivers/fluid_mdriver.c drivers/fluid_mdriver.h - bindings/fluid_cmd.c - bindings/fluid_cmd.h bindings/fluid_filerenderer.c bindings/fluid_ladspa.c bindings/fluid_ladspa.h @@ -249,6 +251,7 @@ add_library ( libfluidsynth-OBJ OBJECT ${fluid_wasapi_SOURCES} ${fluid_waveout_SOURCES} ${fluid_winmidi_SOURCES} + ${fluid_shell_SOURCES} ${fluid_sdl2_SOURCES} ${fluid_libinstpatch_SOURCES} ${libfluidsynth_SOURCES} @@ -276,6 +279,13 @@ if ( LIBFLUID_CPPFLAGS ) PROPERTIES COMPILE_FLAGS ${LIBFLUID_CPPFLAGS} ) endif ( LIBFLUID_CPPFLAGS ) +if ( EMSCRIPTEN_SUPPORT ) + if ( BUILD_SHARED_LIBS ) + add_executable ( libfluidsynth $ ) + else ( BUILD_SHARED_LIBS ) + add_library ( libfluidsynth $ ) + endif ( BUILD_SHARED_LIBS ) +else ( EMSCRIPTEN_SUPPORT ) # Note: by default this target creates a shared object (or dll). To build a # static library instead, set the option BUILD_SHARED_LIBS to FALSE. # Further note: The headers must be explicitly added here to have CMake install @@ -285,6 +295,7 @@ add_library ( libfluidsynth ${public_main_HEADER} ${public_HEADERS} ) +endif ( EMSCRIPTEN_SUPPORT ) if ( MACOSX_FRAMEWORK ) set_source_files_properties ( ${public_HEADERS} @@ -318,6 +329,26 @@ elseif ( WIN32 ) VERSION ${LIB_VERSION_INFO} SOVERSION ${LIB_VERSION_CURRENT} ) +elseif ( EMSCRIPTEN_SUPPORT ) + if ( BUILD_SHARED_LIBS ) + set_target_properties ( libfluidsynth + PROPERTIES + NO_SONAME TRUE + PUBLIC_HEADER "${public_HEADERS}" + PREFIX "lib" + OUTPUT_NAME "fluidsynth" + SUFFIX "-${VERSION}.js" + ) + else ( BUILD_SHARED_LIBS ) + set_target_properties ( libfluidsynth + PROPERTIES + PUBLIC_HEADER "${public_HEADERS}" + PREFIX "lib" + OUTPUT_NAME "fluidsynth" + VERSION ${LIB_VERSION_INFO} + SOVERSION ${LIB_VERSION_CURRENT} + ) + endif ( BUILD_SHARED_LIBS ) else ( MACOSX_FRAMEWORK ) set_target_properties ( libfluidsynth PROPERTIES @@ -356,6 +387,11 @@ endif() if ( TARGET PkgConfig::LIBSNDFILE AND LIBSNDFILE_SUPPORT ) target_link_libraries ( libfluidsynth-OBJ PUBLIC PkgConfig::LIBSNDFILE ) + if ( EMSCRIPTEN_SUPPORT ) + # Manually set dependency libraries + target_link_libraries ( libfluidsynth-OBJ PUBLIC ${LIBSNDFILE_STATIC_LIBRARIES} ) + target_link_directories ( libfluidsynth-OBJ PUBLIC ${LIBSNDFILE_STATIC_LIBRARY_DIRS} ) + endif() endif() if ( TARGET PkgConfig::PULSE AND PULSE_SUPPORT ) @@ -437,6 +473,7 @@ install( TARGETS libfluidsynth-OBJ target_link_libraries ( libfluidsynth PRIVATE libfluidsynth-OBJ ) # ************ CLI program ************ +if ( NOT EMSCRIPTEN_SUPPORT ) set ( fluidsynth_SOURCES fluidsynth.c ) @@ -536,6 +573,8 @@ install(EXPORT FluidSynthTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/fluidsynth ) +endif ( NOT EMSCRIPTEN_SUPPORT ) + # ******* Auto Generated Lookup Tables ****** include(ExternalProject) diff --git a/src/utils/fluid_settings.c b/src/utils/fluid_settings.c index dbee649be..a04a6e1f2 100644 --- a/src/utils/fluid_settings.c +++ b/src/utils/fluid_settings.c @@ -21,7 +21,9 @@ #include "fluid_sys.h" #include "fluid_hash.h" #include "fluid_synth.h" +#ifndef NO_GLIB #include "fluid_cmd.h" +#endif #include "fluid_adriver.h" #include "fluid_mdriver.h" #include "fluid_settings.h" @@ -330,7 +332,9 @@ fluid_settings_init(fluid_settings_t *settings) fluid_return_if_fail(settings != NULL); fluid_synth_settings(settings); +#ifndef NO_GLIB fluid_shell_settings(settings); +#endif fluid_player_settings(settings); fluid_file_renderer_settings(settings); fluid_audio_driver_settings(settings); diff --git a/src/utils/fluid_sys.c b/src/utils/fluid_sys.c index 54bd294be..5e1249d5f 100644 --- a/src/utils/fluid_sys.c +++ b/src/utils/fluid_sys.c @@ -20,6 +20,9 @@ #include "fluid_sys.h" +#ifdef NO_GLIB +#undef NETWORK_SUPPORT +#endif #if WITH_READLINE #include @@ -50,12 +53,14 @@ #define FLUID_SYS_TIMER_HIGH_PRIO_LEVEL 10 +#ifndef NO_GLIB typedef struct { fluid_thread_func_t func; void *data; int prio_level; } fluid_thread_info_t; +#endif struct _fluid_timer_t { @@ -378,7 +383,11 @@ char *fluid_strtok(char **str, char *delim) */ void fluid_msleep(unsigned int msecs) { +#ifndef NO_GLIB g_usleep(msecs * 1000); +#else + usleep(msecs * 1000); +#endif } /** @@ -413,6 +422,7 @@ fluid_utime(void) { double utime; +#ifndef NO_GLIB #if GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 28 /* use high precision monotonic clock if available (g_monotonic_time(). * For Windows, if this clock is actually implemented as low prec. clock @@ -443,6 +453,11 @@ fluid_utime(void) g_get_current_time(&timeval); utime = (timeval.tv_sec * 1000000.0 + timeval.tv_usec); #endif +#else + struct timeval t; + gettimeofday(&t, NULL); + utime = (t.tv_sec * 1000000.0 + t.tv_usec); +#endif return utime; } @@ -995,6 +1010,7 @@ void fluid_profile_start_stop(unsigned int end_ticks, short clear_data) * */ +#ifndef NO_GLIB #if OLD_GLIB_THREAD_API /* Rather than inline this one, we just declare it as a function, to prevent @@ -1127,6 +1143,7 @@ fluid_thread_join(fluid_thread_t *thread) return FLUID_OK; } +#endif /* NO_GLIB */ static fluid_thread_return_t @@ -1197,6 +1214,7 @@ new_fluid_timer(int msec, fluid_timer_callback_t callback, void *data, timer->thread = NULL; timer->auto_destroy = auto_destroy; +#if !defined(NO_GLIB) || defined(USE_PTHREAD) if(new_thread) { timer->thread = new_fluid_thread("timer", fluid_timer_run, timer, high_priority @@ -1209,6 +1227,7 @@ new_fluid_timer(int msec, fluid_timer_callback_t callback, void *data, } } else +#endif { fluid_timer_run(timer); /* Run directly, instead of as a separate thread */ @@ -1244,6 +1263,7 @@ delete_fluid_timer(fluid_timer_t *timer) int fluid_timer_join(fluid_timer_t *timer) { +#if !defined(NO_GLIB) || defined(USE_PTHREAD) int auto_destroy; if(timer->thread) @@ -1256,6 +1276,7 @@ fluid_timer_join(fluid_timer_t *timer) timer->thread = NULL; } } +#endif return FLUID_OK; } diff --git a/src/utils/fluid_sys.h b/src/utils/fluid_sys.h index 8c8284b8e..a3487705e 100644 --- a/src/utils/fluid_sys.h +++ b/src/utils/fluid_sys.h @@ -157,7 +157,15 @@ typedef gintptr intptr_t; #include #endif +#ifndef NO_GLIB #include +#else +#if !defined(__EMSCRIPTEN__) || defined(__EMSCRIPTEN_PTHREADS__) +#include +#define USE_PTHREAD +#endif +#define GLIB_CHECK_VERSION(j, n, p) (0) +#endif /** * Macro used for safely accessing a message from a GError and using a default @@ -182,10 +190,17 @@ char* fluid_get_windows_error(void); #define FLUID_INT_TO_POINTER(x) ((void *)(intptr_t)(x)) /* Endian detection */ +#ifndef NO_GLIB #define FLUID_IS_BIG_ENDIAN (G_BYTE_ORDER == G_BIG_ENDIAN) #define FLUID_LE32TOH(x) GINT32_FROM_LE(x) #define FLUID_LE16TOH(x) GINT16_FROM_LE(x) +#else +#define FLUID_IS_BIG_ENDIAN (__BYTE_ORDER == __BIG_ENDIAN) + +#define FLUID_LE32TOH(x) le32toh(x) +#define FLUID_LE16TOH(x) le16toh(x) +#endif #if FLUID_IS_BIG_ENDIAN #define FLUID_FOURCC(_a, _b, _c, _d) \ @@ -253,6 +268,7 @@ long fluid_timer_get_interval(const fluid_timer_t * timer); /* Muteces */ +#ifndef NO_GLIB #if NEW_GLIB_THREAD_API /* glib 2.32 and newer */ @@ -390,9 +406,143 @@ typedef GStaticPrivate fluid_private_t; #endif +#else /* NO_GLIB */ + +#ifdef USE_PTHREAD + +/* Regular mutex */ +typedef pthread_mutex_t fluid_mutex_t; +#define FLUID_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER +#define fluid_mutex_destroy(_m) pthread_mutex_destroy(&(_m)) +#define fluid_mutex_lock(_m) pthread_mutex_lock(&(_m)) +#define fluid_mutex_unlock(_m) pthread_mutex_unlock(&(_m)) + +static FLUID_INLINE int fluid_mutex_init(fluid_mutex_t *_m) +{ + pthread_mutexattr_t attr; + int r; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + r = pthread_mutex_init(_m, &attr); + pthread_mutexattr_destroy(&attr); + return r; +} + +/* Recursive lock capable mutex */ +typedef pthread_mutex_t fluid_rec_mutex_t; +#define fluid_rec_mutex_destroy(_m) pthread_mutex_destroy(&(_m)) +#define fluid_rec_mutex_lock(_m) pthread_mutex_lock(&(_m)) +#define fluid_rec_mutex_unlock(_m) pthread_mutex_unlock(&(_m)) + +static FLUID_INLINE int fluid_rec_mutex_init(fluid_mutex_t *_m) +{ + pthread_mutexattr_t attr; + int r; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + r = pthread_mutex_init(_m, &attr); + pthread_mutexattr_destroy(&attr); + return r; +} + +/* Dynamically allocated mutex suitable for fluid_cond_t use */ +typedef fluid_mutex_t *fluid_cond_mutex_t; +static FLUID_INLINE void delete_fluid_cond_mutex(fluid_cond_mutex_t *m) +{ + if (!m) + return; + fluid_mutex_destroy(m); + free(m); +} +#define fluid_cond_mutex_lock(m) pthread_mutex_lock(m) +#define fluid_cond_mutex_unlock(m) pthread_mutex_unlock(m) + +static FLUID_INLINE fluid_cond_mutex_t *new_fluid_cond_mutex(void) +{ + fluid_cond_mutex_t *m = (fluid_cond_mutex_t *)malloc(sizeof(fluid_cond_mutex_t)); + if (m) + fluid_mutex_init(m); + return m; +} + +/* Thread condition signaling */ +typedef pthread_cond_t fluid_cond_t; +static FLUID_INLINE fluid_cond_t *new_fluid_cond() +{ + pthread_cond_t *r = (struct pthread_cond_t *)malloc(sizeof(pthread_cond_t)); + if (r) + pthread_cond_init(r, NULL); + return r; +} +static FLUID_INLINE void delete_fluid_cond(fluid_cond_t *cond) +{ + if (!cond) + return; + pthread_cond_destroy(cond); + free(cond); +} +#define fluid_cond_signal(cond) pthread_cond_signal(cond) +#define fluid_cond_broadcast(cond) pthread_cond_broadcast(cond) +#define fluid_cond_wait(cond, mutex) pthread_cond_wait(cond, mutex) + +/* Thread private data */ +typedef pthread_key_t fluid_private_t; +#define fluid_private_get(_priv) pthread_getspecific(&(_priv)) +#define fluid_private_set(_priv, _data) pthread_setspecific(&(_priv), _data) +#define fluid_private_free(_priv) pthread_key_delete((_priv)) +#define fluid_private_init(_priv) pthread_key_create(&(_priv), NULL) + +#else /* USE_PTHREAD */ + +/****** No threading ******/ + +/* Regular mutex */ +typedef int fluid_mutex_t; +#define FLUID_MUTEX_INIT 0 +#define fluid_mutex_destroy(_m) ((void)((_m))) +#define fluid_mutex_lock(_m) ((void)0) +#define fluid_mutex_unlock(_m) ((void)0) + +#define fluid_mutex_init(_m) ((void)((_m))) + +/* Recursive lock capable mutex */ +typedef int fluid_rec_mutex_t; +#define fluid_rec_mutex_destroy(_m) ((void)((_m))) +#define fluid_rec_mutex_lock(_m) ((void)0) +#define fluid_rec_mutex_unlock(_m) ((void)0) +#define fluid_rec_mutex_init(_m) ((void)((_m))) + +/* Dynamically allocated mutex suitable for fluid_cond_t use */ +typedef int *fluid_cond_mutex_t; +#define delete_fluid_cond_mutex(m) free(_m) +#define fluid_cond_mutex_lock(m) ((void)0) +#define fluid_cond_mutex_unlock(m) ((void)0) +#define new_fluid_cond_mutex(_m) ((fluid_cond_mutex_t *)malloc(sizeof(fluid_cond_mutex_t))) + +/* Thread condition signaling */ +typedef int fluid_cond_t; +#define new_fluid_cond() ((fluid_cond_t)1) +#define delete_fluid_cond(cond) ((void)((cond))) +#define fluid_cond_signal(cond) ((void)0) +#define fluid_cond_broadcast(cond) ((void)0) +#define fluid_cond_wait(cond, mutex) ((void)0) + +/* Thread private data */ +typedef void **fluid_private_t; +#define fluid_private_get(_priv) (*(_priv)) +#define fluid_private_set(_priv, _data) ((void)((*(_priv) = (_data)), 0)) +#define fluid_private_free(_priv) free((_priv)) +#define fluid_private_init(_priv) ((void)((_priv = (fluid_private_t) malloc(sizeof(void*))), 0)) + +#endif + +#endif /* NO_GLIB */ + /* Atomic operations */ +#ifndef NO_GLIB + #define fluid_atomic_int_inc(_pi) g_atomic_int_inc(_pi) #define fluid_atomic_int_get(_pi) g_atomic_int_get(_pi) #define fluid_atomic_int_set(_pi, _val) g_atomic_int_set(_pi, _val) @@ -417,6 +567,52 @@ typedef GStaticPrivate fluid_private_t; #define fluid_atomic_pointer_compare_and_exchange(_pp, _old, _new) \ g_atomic_pointer_compare_and_exchange(_pp, _old, _new) +#else + +/* no atomic */ + +#define fluid_atomic_int_inc(_pi) ((void)((*(_pi))++)) +#define fluid_atomic_int_get(_pi) (*(_pi)) +#define fluid_atomic_int_set(_pi, _val) ((void)(*(_pi) = (_val))) +#define fluid_atomic_int_dec_and_test(_pi) (--*(_pi) == 0) +static FLUID_INLINE int fluid_atomic_int_compare_and_exchange(volatile int *_pi, int _old, int _new) +{ + if (*_pi == _old) + { + *_pi = _new; + return TRUE; + } + else + { + return FALSE; + } +} + +static FLUID_INLINE int fluid_atomic_int_exchange_and_add(volatile int *_pi, int _add) +{ + int tmp = *_pi; + *_pi += _add; + return tmp; +} +#define fluid_atomic_int_add(_pi, _add) fluid_atomic_int_exchange_and_add(_pi, _add) + +#define fluid_atomic_pointer_get(_pp) (*(_pp)) +#define fluid_atomic_pointer_set(_pp, val) ((void)(*(_pp) = val)) +static FLUID_INLINE int fluid_atomic_pointer_compare_and_exchange(volatile void **_pp, void *_old, void *_new) +{ + if (*_pp == _old) + { + *_pp = _new; + return TRUE; + } + else + { + return FALSE; + } +} + +#endif /* NO_GLIB */ + static FLUID_INLINE void fluid_atomic_float_set(fluid_atomic_float_t *fptr, float val) { @@ -443,6 +639,8 @@ typedef void *fluid_thread_return_t; /* static return value for thread functions which requires a return value */ #define FLUID_THREAD_RETURN_VALUE (NULL) +#ifndef NO_GLIB + typedef GThread fluid_thread_t; typedef fluid_thread_return_t (*fluid_thread_func_t)(void *data); @@ -469,6 +667,53 @@ typedef GModule fluid_module_t; #endif /* LADSPA */ +#else /* NO_GLIB */ + +#if defined(USE_PTHREAD) + +typedef pthread_t fluid_thread_t; +typedef fluid_thread_return_t (*fluid_thread_func_t)(void *data); + +// #define FLUID_THREAD_ID_NULL NULL /* A NULL "ID" value */ +// #define fluid_thread_id_t pthread_t /* Data type for a thread ID */ +// #define fluid_thread_get_id() pthread_self() /* Get unique "ID" for current thread */ + +static FLUID_INLINE fluid_thread_t * +new_fluid_thread(const char *name, fluid_thread_func_t func, void *data, int prio_level, int detach) +{ + fluid_thread_t *t; + pthread_attr_t attr; + int err; + struct sched_param sched = {0}; + + t = (fluid_thread_t *)malloc(sizeof(fluid_thread_t)); + if (t) + { + sched.sched_priority = prio_level; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, detach); + pthread_attr_setschedparam(&attr, &sched); + + r = pthread_create(t, &attr, func, data); + pthread_attr_destroy(&attr); + if (r != 0) + { + free(t); + return NULL; + } + } + return t; +} +#define delete_fluid_thread(_pthread) free(_pthread) +#define fluid_thread_self_set_prio(prio_level) pthread_setschedprio(pthread_self(), (prio_level)) +#define fluid_thread_join(_pthread) (pthread_join(*_pthread, NULL), FLUID_OK) + +#else /* defined(USE_PTHREAD) */ +typedef void *fluid_thread_t; +#endif /* defined(USE_PTHREAD) */ + +#endif /* NO_GLIB */ + /* Sockets and I/O */ int fluid_istream_readline(fluid_istream_t in, fluid_ostream_t out, char *prompt, char *buf, int len); @@ -493,8 +738,7 @@ fluid_istream_t fluid_socket_get_istream(fluid_socket_t sock); fluid_ostream_t fluid_socket_get_ostream(fluid_socket_t sock); /* File access */ -#define fluid_stat(_filename, _statbuf) g_stat((_filename), (_statbuf)) -#if !GLIB_CHECK_VERSION(2, 26, 0) +#if defined(NO_GLIB) || !GLIB_CHECK_VERSION(2, 26, 0) /* GStatBuf has not been introduced yet, manually typedef to what they had at that time: * https://github.com/GNOME/glib/blob/e7763678b56e3be073cc55d707a6e92fc2055ee0/glib/gstdio.h#L98-L115 */ @@ -508,8 +752,13 @@ fluid_ostream_t fluid_socket_get_ostream(fluid_socket_t sock); /* posix, OS/2, etc. */ typedef struct stat fluid_stat_buf_t; #endif + #define fluid_stat(_filename, _statbuf) stat((_filename), (_statbuf)) + #if defined(NO_GLIB) + #define g_file_test(file, test) (1) + #endif #else typedef GStatBuf fluid_stat_buf_t; +#define fluid_stat(_filename, _statbuf) g_stat((_filename), (_statbuf)) #endif FILE* fluid_file_open(const char* filename, const char** errMsg); diff --git a/src/utils/fluidsynth_priv.h b/src/utils/fluidsynth_priv.h index ce5fb7fdd..7dfc91386 100644 --- a/src/utils/fluidsynth_priv.h +++ b/src/utils/fluidsynth_priv.h @@ -31,7 +31,9 @@ #include "config.h" +#ifndef NO_GLIB #include +#endif #if HAVE_STDLIB_H #include // malloc, free @@ -48,10 +50,18 @@ #include "fluidsynth.h" +#if defined(NO_GLIB) +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif +#endif + #ifdef __cplusplus extern "C" { #endif + /*************************************************************** * * BASIC TYPES @@ -63,7 +73,7 @@ typedef float fluid_real_t; typedef double fluid_real_t; #endif -#if defined(SUPPORTS_VLA) +#if defined(SUPPORTS_VLA) || defined(NO_GLIB) # define FLUID_DECLARE_VLA(_type, _name, _len) \ _type _name[_len] #else @@ -287,6 +297,7 @@ do { strncpy(_dst,_src,_n-1); \ #define FLUID_LOG fluid_log #endif +#ifndef NO_GLIB #if defined(DEBUG) && !defined(NDEBUG) #define FLUID_ASSERT(a) g_assert(a) #else @@ -296,6 +307,19 @@ do { strncpy(_dst,_src,_n-1); \ #define FLUID_LIKELY G_LIKELY #define FLUID_UNLIKELY G_UNLIKELY +#else +#define FLUID_ASSERT(a) + +#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 303) +#define FLUID_LIKELY(x) __builtin_expect(!!(x), 1) +#define FLUID_UNLIKELY(x) __builtin_expect(!!(x), 0) +#else +#define FLUID_LIKELY(x) (x) +#define FLUID_UNLIKELY(x) (x) +#endif +#endif + +char *fluid_error(void); /* Misc */ #if defined(__INTEL_COMPILER) #define FLUID_RESTRICT restrict From 194cf7bd83e2322e32e3c0863606954a765111b4 Mon Sep 17 00:00:00 2001 From: jet2jet <34238471+jet2jet@users.noreply.github.com> Date: Sun, 28 Oct 2018 22:30:59 +0900 Subject: [PATCH 2/9] [fluidsynth-emscripten] rename original README.md to add fluidsynth-emscripten's README.md --- README.md => README.original.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename README.md => README.original.md (100%) diff --git a/README.md b/README.original.md similarity index 100% rename from README.md rename to README.original.md From 718b5238d5321a21ac37341b575d40eaa62814c3 Mon Sep 17 00:00:00 2001 From: jet2jet <34238471+jet2jet@users.noreply.github.com> Date: Tue, 27 Dec 2022 21:01:19 +0900 Subject: [PATCH 3/9] [fluidsynth-emscripten] Add readme for this repository --- README.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 000000000..981ae3c98 --- /dev/null +++ b/README.md @@ -0,0 +1,46 @@ + +# FluidSynth with Emscripten-specific patch + +This repository is based on [FluidSynth](https://github.com/FluidSynth/fluidsynth) repository, and contains some changes to build with Emscripten. + +The original README is here: [README.original.md](./README.original.md) + +## Build + +> Tested with Emscripten version 3.1.10. + +1. (Optional) Update `emscripten/exports.txt`, containing export functions for JS program + * The script `emscripten/make-exports.js` will update this automatically, gathering functions from `include` directory. +2. Make sure that Emscripten is usable on the current environment +3. Make `build` directory +4. Enter `build` directory and execute `emcmake cmake -Denable-oss=off -DCMAKE_BUILD_TYPE=Release ..` + * If no other options are specified, and `cmake` is running with `emcmake` (or `emconfigure`), the build configurations are initialized for Emscripten-build mode. +5. In `build` directory, execute `emmake make` + +After successful build, `libfluidsynth-.js` will be created at `build/src` directory. + +* If `enable-debug` specified on the `cmake` execution (e.g. `emcmake cmake -Denable-debug=on ..`), a map file `libfluidsynth-.wasm.map` is also generated. + * Currently it seems that it cannot be used. +* If `enable-separate-wasm` specified on the `cmake` execution (e.g. `emcmake cmake -Denable-separate-wasm=on ..`), `libfluidsynth-.wasm` and `libfluidsynth-.wast` are also generated. + * For AudioWorklet, you cannot use `*.wasm` file directly. +* In Emscripten-build mode, standalone application named `fluidsynth` is not emitted. + +## Build static library for Emscripten + +Please specify `-D BUILD_SHARED_LIBS=off` on calling emcmake. (e.g. `emcmake cmake -D BUILD_SHARED_LIBS=off ..`) + +In this mode, you can also build sources under `doc` directory (e.g. `cd build/doc && make fluidsynth_simple -j16`), although all exportable functions will be exported. + +## Usage + +Place `libfluidsynth-.js` file to your space and load `libfluidsynth-.js`. After load, almost all FluidSynth API functions are accessible via `Module` object (note that all function names have the prefix `_`). + +To use `libfluidsynth-.js` in AudioWorklet, load it into AudioWorklet before your worklet JS file. In your worklet JS file, you can access `Module` object via `AudioWorkletGlobalScope.wasmModule`. + +## Miscellaneous + +* Currently only several APIs are tested. Some APIs such as for drivers may not work. + +## License + +This program and all source codes, including the original FluidSynth program, its source codes, modifications of FluidSynth source codes for building library with Emscripten, and sources codes used only for building `libfluidsynth-.js`, are licensed under [GNU Lesser General Public License (v2.1)](./LICENSE) (LGPL v2.1). From b218e00eb05e84c7c1e76c65ae7a1aceb291a389 Mon Sep 17 00:00:00 2001 From: Joe Meadows Date: Fri, 14 Jul 2023 15:41:12 -0700 Subject: [PATCH 4/9] After upgrading from fluidsynth-emscripten-2.2.1 to 2.3.0 I ran into problems trying to load the module. There are also some changes here that I had previously made for 2.2.1. With these changes I am able to build and load fluidsynth as an AudioWorklet processor. From v2.2.1 also needed in v2.3.0 - Added some additional EXPORTS to CMakelists.txt to fix runtime unresolveds: addFunction,removeFunction,MEMFS,lengthBytesUTF8,UTF8ArrayToString,UTF8ToString,stringToUTF8Array,stringToUTF8. Additional change for 2.3.0 Failed to Base64 decode the WASM binary b/c atob() didn't exist. Maybe it's not defined in the AudioWorklet scope? I put back a polyfill that was in the 2.2.1 code, added this to pre.js. Build tools: emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.43 (a6b8143cf3c1171db911750359456b15a8deece7) clang version 17.0.0 (https://github.com/llvm/llvm-project 71513a71cdf380efd6a44be6939e2cb979a62407) Target: wasm32-unknown-emscripten Thread model: posix Tested on Chrome Version 114.0.5735.133 (Official Build) (64-bit) Significant possibility that this is user error on my part, but I was not able to find another solution. --- CMakeLists.txt | 2 +- emscripten/src/pre.js | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dcdaf7b20..636c568a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -708,7 +708,7 @@ else (NOT EMSCRIPTEN_SUPPORT) if ( NOT enable-separate-wasm ) SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s SINGLE_FILE=1" ) endif ( NOT enable-separate-wasm ) - SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --pre-js ${CMAKE_SOURCE_DIR}/emscripten/src/pre.js -s ENVIRONMENT=web -s INITIAL_MEMORY=67108864 -s ALLOW_MEMORY_GROWTH=1 -s ALLOW_TABLE_GROWTH=1 -s EXPORTED_FUNCTIONS='[${EMSCRIPTEN_EXPORTS_OPTIONS}]' -s 'EXTRA_EXPORTED_RUNTIME_METHODS=[\"ccall\", \"cwrap\", \"FS\"]'" ) + SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --pre-js ${CMAKE_SOURCE_DIR}/emscripten/src/pre.js -s ENVIRONMENT=web -s INITIAL_MEMORY=67108864 -s ALLOW_MEMORY_GROWTH=1 -s ALLOW_TABLE_GROWTH=1 -s EXPORTED_FUNCTIONS='[${EMSCRIPTEN_EXPORTS_OPTIONS}]' -s 'EXTRA_EXPORTED_RUNTIME_METHODS=[\"ccall\", \"cwrap\", \"FS\",\"addFunction\",\"removeFunction\",\"MEMFS\",\"lengthBytesUTF8\",\"UTF8ArrayToString\",\"UTF8ToString\",\"stringToUTF8Array\",\"stringToUTF8\"]'" ) SET( CMAKE_EXECUTABLE_SUFFIX ".js" ) find_package ( PkgConfig REQUIRED ) diff --git a/emscripten/src/pre.js b/emscripten/src/pre.js index dd6379501..08a2d3c89 100644 --- a/emscripten/src/pre.js +++ b/emscripten/src/pre.js @@ -4,6 +4,37 @@ var document = typeof document !== 'undefined' ? document : {}; var window = typeof window !== 'undefined' ? window : {}; // expose wasm API to AudioWorklet if (typeof AudioWorkletGlobalScope !== 'undefined' && AudioWorkletGlobalScope) { + var atob = function (input) { + var keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + + var output = ''; + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0; + // remove all characters that are not A-Z, a-z, 0-9, +, /, or = + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ''); + do { + enc1 = keyStr.indexOf(input.charAt(i++)); + enc2 = keyStr.indexOf(input.charAt(i++)); + enc3 = keyStr.indexOf(input.charAt(i++)); + enc4 = keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output = output + String.fromCharCode(chr1); + + if (enc3 !== 64) { + output = output + String.fromCharCode(chr2); + } + if (enc4 !== 64) { + output = output + String.fromCharCode(chr3); + } + } while (i < input.length); + return output; + }; + AudioWorkletGlobalScope.wasmModule = Module; AudioWorkletGlobalScope.wasmAddFunction = addFunction; AudioWorkletGlobalScope.wasmRemoveFunction = removeFunction; From 607d731f4158c51645f6ff34305ac9af7a52d792 Mon Sep 17 00:00:00 2001 From: MengLinMaker Date: Sun, 29 Sep 2024 00:01:20 +1000 Subject: [PATCH 5/9] Add sndfile dependency with vcpkg package manager --- .gitignore | 3 +++ vcpkg-configuration.json | 14 ++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 vcpkg-configuration.json diff --git a/.gitignore b/.gitignore index 38ce42d38..172a8b9a7 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,6 @@ install_manifest.txt # ProjectFiles *.pro.user* *.user + +# Package manager +vcpkg_installed diff --git a/vcpkg-configuration.json b/vcpkg-configuration.json new file mode 100644 index 000000000..1b3683687 --- /dev/null +++ b/vcpkg-configuration.json @@ -0,0 +1,14 @@ +{ + "default-registry": { + "kind": "git", + "baseline": "fc358711d78c5dcb8f240daea628ecfee60fb164", + "repository": "https://github.com/microsoft/vcpkg" + }, + "registries": [ + { + "kind": "artifact", + "location": "https://github.com/microsoft/vcpkg-ce-catalog/archive/refs/heads/main.zip", + "name": "microsoft" + } + ] +} From cd5f4ddabe327fbd75bce71975eba685eb94b444 Mon Sep 17 00:00:00 2001 From: MengLinMaker Date: Sun, 29 Sep 2024 01:44:04 +1000 Subject: [PATCH 6/9] C99 float math not required for wasm compilation --- CMakeLists.txt | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 636c568a1..035c0523b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -827,44 +827,6 @@ set(TEST_MIDI_UTF8 "${FluidSynth_SOURCE_DIR}/test/èmpty.mid") # Make sure to link against libm before checking for math functions below set ( CMAKE_REQUIRED_LIBRARIES "${LIBFLUID_LIBS};${WINDOWS_LIBS}" ) -# Check for C99 float math - -unset ( HAVE_SINF CACHE ) -CHECK_SYMBOL_EXISTS ( sinf "math.h" HAVE_SINF ) -if ( HAVE_SINF ) - set ( HAVE_SINF 1 ) -endif ( HAVE_SINF ) - -unset ( HAVE_COSF CACHE ) -CHECK_SYMBOL_EXISTS ( cosf "math.h" HAVE_COSF ) -if ( HAVE_COSF ) - set ( HAVE_COSF 1 ) -endif ( HAVE_COSF ) - -unset ( HAVE_FABSF CACHE ) -CHECK_SYMBOL_EXISTS ( fabsf "math.h" HAVE_FABSF ) -if ( HAVE_FABSF ) - set ( HAVE_FABSF 1 ) -endif ( HAVE_FABSF ) - -unset ( HAVE_POWF CACHE ) -CHECK_SYMBOL_EXISTS ( powf "math.h" HAVE_POWF ) -if ( HAVE_POWF ) - set ( HAVE_POWF 1 ) -endif ( HAVE_POWF ) - -unset ( HAVE_SQRTF CACHE ) -CHECK_SYMBOL_EXISTS ( sqrtf "math.h" HAVE_SQRTF ) -if ( HAVE_SQRTF ) - set ( HAVE_SQRTF 1 ) -endif ( HAVE_SQRTF ) - -unset ( HAVE_LOGF CACHE ) -CHECK_SYMBOL_EXISTS ( logf "math.h" HAVE_LOGF ) -if ( HAVE_LOGF ) - set ( HAVE_LOGF 1 ) -endif ( HAVE_LOGF ) - unset ( HAVE_INETNTOP CACHE ) unset ( IPV6_SUPPORT CACHE ) if ( WIN32 ) From 40b17154beed7539b501d2b893272b5057b121a1 Mon Sep 17 00:00:00 2001 From: MengLinMaker Date: Sun, 29 Sep 2024 02:19:40 +1000 Subject: [PATCH 7/9] Default options off to reduce dependencies and binary size --- CMakeLists.txt | 86 +++++++++++++++++++++++++------------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 035c0523b..387553039 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,50 +71,50 @@ option ( enable-portaudio "compile PortAudio support" off ) option ( enable-profiling "profile the dsp code" off ) option ( enable-trap-on-fpe "enable SIGFPE trap on Floating Point Exceptions" off ) option ( enable-ubsan "compile and link against UBSan (for debugging fluidsynth internals)" off ) +option ( enable-aufile "compile support for sound file output" off ) +option ( enable-dbus "compile DBUS support (if it is available)" off ) +option ( enable-ipv6 "enable ipv6 support" off ) +option ( enable-jack "compile JACK support (if it is available)" off ) +option ( enable-ladspa "enable LADSPA effect units" off ) +option ( enable-libinstpatch "use libinstpatch (if available) to load DLS and GIG files" off ) +option ( enable-libsndfile "compile libsndfile support (if it is available)" off ) +option ( enable-midishare "compile MidiShare support (if it is available)" off ) +option ( enable-opensles "compile OpenSLES support (if it is available)" off ) +option ( enable-oboe "compile Oboe support (requires OpenSLES and/or AAudio)" off ) +option ( enable-network "enable network support (requires BSD sockets)" off ) +option ( enable-oss "compile OSS support (if it is available)" off ) +option ( enable-dsound "compile DirectSound support (if it is available)" off ) +option ( enable-wasapi "compile Windows WASAPI support (if it is available)" off ) +option ( enable-waveout "compile Windows WaveOut support (if it is available)" off ) +option ( enable-winmidi "compile Windows MIDI support (if it is available)" off ) +option ( enable-sdl2 "compile SDL2 audio support (if it is available)" off ) +option ( enable-pulseaudio "compile PulseAudio support (if it is available)" off ) +option ( enable-pipewire "compile PipeWire support (if it is available)" off ) +option ( enable-readline "compile readline lib line editing (if it is available)" off ) +option ( enable-threads "enable multi-threading support (such as parallel voice synthesis)" off ) +option ( enable-openmp "enable OpenMP support (parallelization of soundfont decoding, vectorization of voice mixing, etc.)" off ) # Options enabled by default -option ( enable-aufile "compile support for sound file output" on ) option ( BUILD_SHARED_LIBS "Build a shared object or DLL" on ) -option ( enable-dbus "compile DBUS support (if it is available)" on ) -option ( enable-ipv6 "enable ipv6 support" on ) -option ( enable-jack "compile JACK support (if it is available)" on ) -option ( enable-ladspa "enable LADSPA effect units" on ) -option ( enable-libinstpatch "use libinstpatch (if available) to load DLS and GIG files" on ) -option ( enable-libsndfile "compile libsndfile support (if it is available)" on ) -option ( enable-midishare "compile MidiShare support (if it is available)" on ) -option ( enable-opensles "compile OpenSLES support (if it is available)" off ) -option ( enable-oboe "compile Oboe support (requires OpenSLES and/or AAudio)" off ) -option ( enable-network "enable network support (requires BSD sockets)" on ) -option ( enable-oss "compile OSS support (if it is available)" on ) -option ( enable-dsound "compile DirectSound support (if it is available)" on ) -option ( enable-wasapi "compile Windows WASAPI support (if it is available)" on ) -option ( enable-waveout "compile Windows WaveOut support (if it is available)" on ) -option ( enable-winmidi "compile Windows MIDI support (if it is available)" on ) -option ( enable-sdl2 "compile SDL2 audio support (if it is available)" on ) -option ( enable-pulseaudio "compile PulseAudio support (if it is available)" on ) -option ( enable-pipewire "compile PipeWire support (if it is available)" on ) -option ( enable-readline "compile readline lib line editing (if it is available)" on ) -option ( enable-threads "enable multi-threading support (such as parallel voice synthesis)" on ) -option ( enable-openmp "enable OpenMP support (parallelization of soundfont decoding, vectorization of voice mixing, etc.)" on ) # Platform specific options if ( CMAKE_SYSTEM MATCHES "Linux|FreeBSD|DragonFly" ) - option ( enable-lash "compile LASH support (if it is available)" on ) - option ( enable-alsa "compile ALSA support (if it is available)" on ) + option ( enable-lash "compile LASH support (if it is available)" off ) + option ( enable-alsa "compile ALSA support (if it is available)" off ) endif ( CMAKE_SYSTEM MATCHES "Linux|FreeBSD|DragonFly" ) if ( CMAKE_SYSTEM MATCHES "Linux" ) - option ( enable-systemd "compile systemd support (if it is available)" on ) + option ( enable-systemd "compile systemd support (if it is available)" off ) endif ( CMAKE_SYSTEM MATCHES "Linux" ) if ( CMAKE_SYSTEM MATCHES "Darwin" ) - option ( enable-coreaudio "compile CoreAudio support (if it is available)" on ) - option ( enable-coremidi "compile CoreMIDI support (if it is available)" on ) - option ( enable-framework "create a Mac OSX style FluidSynth.framework" on ) + option ( enable-coreaudio "compile CoreAudio support (if it is available)" off ) + option ( enable-coremidi "compile CoreMIDI support (if it is available)" off ) + option ( enable-framework "create a Mac OSX style FluidSynth.framework" off ) endif ( CMAKE_SYSTEM MATCHES "Darwin" ) if ( CMAKE_SYSTEM MATCHES "OS2" ) - option ( enable-dart "compile DART support (if it is available)" on ) + option ( enable-dart "compile DART support (if it is available)" off ) set ( enable-ipv6 off ) endif ( CMAKE_SYSTEM MATCHES "OS2" ) @@ -510,7 +510,7 @@ endif ( GLIB_glib-2.0_VERSION AND GLIB_glib-2.0_VERSION VERSION_LESS "2.26.0" ) unset ( LIBSNDFILE_SUPPORT CACHE ) unset ( LIBSNDFILE_HASVORBIS CACHE ) if ( enable-libsndfile ) -pkg_check_modules ( LIBSNDFILE sndfile>=1.0.0 IMPORTED_TARGET ) +pkg_check_modules ( LIBSNDFILE REQUIRED sndfile>=1.0.0 IMPORTED_TARGET ) set ( LIBSNDFILE_SUPPORT ${LIBSNDFILE_FOUND} ) if ( LIBSNDFILE_SUPPORT ) #[[ cmake_print_variables ( @@ -541,7 +541,7 @@ endif ( enable-libsndfile ) unset ( PULSE_SUPPORT CACHE ) if ( enable-pulseaudio ) - pkg_check_modules ( PULSE libpulse-simple>=0.9.8 IMPORTED_TARGET ) + pkg_check_modules ( PULSE REQUIRED libpulse-simple>=0.9.8 IMPORTED_TARGET ) set ( PULSE_SUPPORT ${PULSE_FOUND} ) if ( PULSE_SUPPORT ) list( APPEND PC_REQUIRES_PRIV "libpulse-simple") @@ -552,7 +552,7 @@ endif ( enable-pulseaudio ) unset ( ALSA_SUPPORT CACHE ) if ( enable-alsa ) - pkg_check_modules ( ALSA alsa>=0.9.1 IMPORTED_TARGET ) + pkg_check_modules ( ALSA REQUIRED alsa>=0.9.1 IMPORTED_TARGET ) set ( ALSA_SUPPORT ${ALSA_FOUND} ) if ( ALSA_SUPPORT ) list( APPEND PC_REQUIRES_PRIV "alsa") @@ -563,7 +563,7 @@ endif ( enable-alsa ) unset ( PORTAUDIO_SUPPORT CACHE ) if ( enable-portaudio ) - pkg_check_modules ( PORTAUDIO portaudio-2.0>=19 IMPORTED_TARGET ) + pkg_check_modules ( PORTAUDIO REQUIRED portaudio-2.0>=19 IMPORTED_TARGET ) set ( PORTAUDIO_SUPPORT ${PORTAUDIO_FOUND} ) if ( PORTAUDIO_SUPPORT ) list( APPEND PC_REQUIRES_PRIV "portaudio-2.0") @@ -574,7 +574,7 @@ endif ( enable-portaudio ) unset ( JACK_SUPPORT CACHE ) if ( enable-jack ) - pkg_check_modules ( JACK jack IMPORTED_TARGET ) + pkg_check_modules ( JACK REQUIRED jack IMPORTED_TARGET ) set ( JACK_SUPPORT ${JACK_FOUND} ) if (JACK_SUPPORT) sanitize_target_dirs(PkgConfig::JACK) @@ -586,7 +586,7 @@ endif ( enable-jack ) unset ( PIPEWIRE_SUPPORT CACHE ) if ( enable-pipewire ) - pkg_check_modules ( PIPEWIRE libpipewire-0.3 IMPORTED_TARGET ) + pkg_check_modules ( PIPEWIRE REQUIRED libpipewire-0.3 IMPORTED_TARGET ) set ( PIPEWIRE_SUPPORT ${PIPEWIRE_FOUND} ) if ( PIPEWIRE_SUPPORT ) list( APPEND PC_REQUIRES_PRIV "libpipewire-0.3") @@ -597,7 +597,7 @@ endif ( enable-pipewire ) unset ( LASH_SUPPORT CACHE ) if ( enable-lash ) - pkg_check_modules ( LASH lash-1.0>=0.3 IMPORTED_TARGET ) + pkg_check_modules ( LASH REQUIRED lash-1.0>=0.3 IMPORTED_TARGET ) if ( LASH_FOUND ) set ( LASH_SUPPORT 1 ) add_definitions ( -DHAVE_LASH ) @@ -611,7 +611,7 @@ endif ( enable-lash ) unset ( SYSTEMD_SUPPORT CACHE ) if ( enable-systemd ) - pkg_check_modules ( SYSTEMD libsystemd IMPORTED_TARGET ) + pkg_check_modules ( SYSTEMD REQUIRED libsystemd IMPORTED_TARGET ) set ( SYSTEMD_SUPPORT ${SYSTEMD_FOUND} ) if ( SYSTEMD_SUPPORT ) list( APPEND PC_REQUIRES_PRIV "libsystemd") @@ -622,7 +622,7 @@ endif ( enable-systemd ) unset ( DBUS_SUPPORT CACHE ) if ( enable-dbus ) -pkg_check_modules ( DBUS dbus-1>=1.0.0 IMPORTED_TARGET ) +pkg_check_modules ( DBUS REQUIRED dbus-1>=1.0.0 IMPORTED_TARGET ) set ( DBUS_SUPPORT ${DBUS_FOUND} ) if ( DBUS_SUPPORT ) list( APPEND PC_REQUIRES_PRIV "dbus-1") @@ -643,7 +643,7 @@ endif ( enable-ladspa ) unset ( LIBINSTPATCH_SUPPORT CACHE ) if ( enable-libinstpatch ) - pkg_check_modules ( LIBINSTPATCH libinstpatch-1.0>=1.1.0 IMPORTED_TARGET ) + pkg_check_modules ( LIBINSTPATCH REQUIRED libinstpatch-1.0>=1.1.0 IMPORTED_TARGET ) set ( LIBINSTPATCH_SUPPORT ${LIBINSTPATCH_FOUND} ) if ( LIBINSTPATCH_SUPPORT ) list( APPEND PC_REQUIRES_PRIV "libinstpatch-1.0") @@ -660,7 +660,7 @@ endif ( enable-libinstpatch ) unset ( SDL2_SUPPORT CACHE ) if ( enable-sdl2 ) - pkg_check_modules ( SDL2 sdl2>=2.0.4 IMPORTED_TARGET ) + pkg_check_modules ( SDL2 REQUIRED sdl2>=2.0.4 IMPORTED_TARGET ) set ( SDL2_SUPPORT ${SDL2_FOUND} ) if ( SDL2_SUPPORT ) list( APPEND PC_REQUIRES_PRIV "sdl2") @@ -671,7 +671,7 @@ endif ( enable-sdl2 ) unset ( OBOE_SUPPORT CACHE ) if ( enable-oboe ) - pkg_check_modules ( OBOE oboe-1.0 IMPORTED_TARGET ) + pkg_check_modules ( OBOE REQUIRED oboe-1.0 IMPORTED_TARGET ) if ( OBOE_FOUND ) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -683,7 +683,7 @@ endif ( enable-oboe ) unset ( WITH_READLINE CACHE ) unset ( READLINE_LIBS CACHE ) if ( enable-readline ) -pkg_check_modules ( READLINE readline QUIET IMPORTED_TARGET ) +pkg_check_modules ( READLINE REQUIRED readline QUIET IMPORTED_TARGET ) if ( READLINE_FOUND ) list( APPEND PC_REQUIRES_PRIV "readline") else ( READLINE_FOUND ) @@ -717,7 +717,7 @@ else (NOT EMSCRIPTEN_SUPPORT) unset ( LIBSNDFILE_SUPPORT CACHE ) unset ( LIBSNDFILE_HASVORBIS CACHE ) if ( enable-libsndfile ) - pkg_check_modules ( LIBSNDFILE sndfile>=1.0.0 IMPORTED_TARGET ) + pkg_check_modules ( LIBSNDFILE REQUIRED sndfile>=1.0.0 IMPORTED_TARGET ) set ( LIBSNDFILE_SUPPORT ${LIBSNDFILE_FOUND} ) if ( LIBSNDFILE_SUPPORT ) # Patch to use 'opus' From 23247a225b68d35fbd077154e479d955c9e8a56e Mon Sep 17 00:00:00 2001 From: MengLinMaker Date: Sun, 29 Sep 2024 02:49:18 +1000 Subject: [PATCH 8/9] Add vcpkg build config for libsndfile --- CMakeLists.txt | 4 ++++ CMakePresets.json | 24 ++++++++++++++++++++++++ vcpkg.json | 7 +++++++ 3 files changed, 35 insertions(+) create mode 100644 CMakePresets.json create mode 100644 vcpkg.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 387553039..f529863d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,10 @@ # CMake based build system. Pedro Lopez-Cabanillas cmake_minimum_required ( VERSION 3.13 ) + +# Configure where pkgconfig finds vcpkg .pc files +set(ENV{PKG_CONFIG_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg_installed/wasm32-emscripten/lib/pkgconfig") + # 3.1 because of CMAKE_C_STANDARD # 3.11 because COMPATIBILITY SameMinorVersion in CMakePackageConfigHelpers # 3.13.5 because it is the latest supported in Windows XP diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 000000000..5d6e8eeb4 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,24 @@ +{ + "version": 6, + "cmakeMinimumRequired": { + "major": 3, + "minor": 13, + "patch": 0 + }, + "configurePresets": [ + { + "name": "wasm", + "generator": "", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RELEASE" + } + }, + { + "name": "wasm-libsndfile", + "inherits": "wasm", + "cacheVariables": { + "enable-libsndfile": "on" + } + } + ] +} \ No newline at end of file diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 000000000..6bcc240a1 --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,7 @@ +{ + "name": "libfluidsynth", + "version": "2.3.0", + "dependencies": [ + "sndfile" + ] +} From dd29c9ad0a318a7638557cc5add8e88aa6d0f9e4 Mon Sep 17 00:00:00 2001 From: MengLinMaker Date: Fri, 4 Oct 2024 11:24:57 +1000 Subject: [PATCH 9/9] Revert "C99 float math not required for wasm compilation" This reverts commit cd5f4ddabe327fbd75bce71975eba685eb94b444. --- CMakeLists.txt | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index f529863d7..aebd921a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -831,6 +831,44 @@ set(TEST_MIDI_UTF8 "${FluidSynth_SOURCE_DIR}/test/èmpty.mid") # Make sure to link against libm before checking for math functions below set ( CMAKE_REQUIRED_LIBRARIES "${LIBFLUID_LIBS};${WINDOWS_LIBS}" ) +# Check for C99 float math + +unset ( HAVE_SINF CACHE ) +CHECK_SYMBOL_EXISTS ( sinf "math.h" HAVE_SINF ) +if ( HAVE_SINF ) + set ( HAVE_SINF 1 ) +endif ( HAVE_SINF ) + +unset ( HAVE_COSF CACHE ) +CHECK_SYMBOL_EXISTS ( cosf "math.h" HAVE_COSF ) +if ( HAVE_COSF ) + set ( HAVE_COSF 1 ) +endif ( HAVE_COSF ) + +unset ( HAVE_FABSF CACHE ) +CHECK_SYMBOL_EXISTS ( fabsf "math.h" HAVE_FABSF ) +if ( HAVE_FABSF ) + set ( HAVE_FABSF 1 ) +endif ( HAVE_FABSF ) + +unset ( HAVE_POWF CACHE ) +CHECK_SYMBOL_EXISTS ( powf "math.h" HAVE_POWF ) +if ( HAVE_POWF ) + set ( HAVE_POWF 1 ) +endif ( HAVE_POWF ) + +unset ( HAVE_SQRTF CACHE ) +CHECK_SYMBOL_EXISTS ( sqrtf "math.h" HAVE_SQRTF ) +if ( HAVE_SQRTF ) + set ( HAVE_SQRTF 1 ) +endif ( HAVE_SQRTF ) + +unset ( HAVE_LOGF CACHE ) +CHECK_SYMBOL_EXISTS ( logf "math.h" HAVE_LOGF ) +if ( HAVE_LOGF ) + set ( HAVE_LOGF 1 ) +endif ( HAVE_LOGF ) + unset ( HAVE_INETNTOP CACHE ) unset ( IPV6_SUPPORT CACHE ) if ( WIN32 )