From 5f4c8ea6545bc36c355b1b88062230487ecb102f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 21 Oct 2017 02:10:33 -0700 Subject: [PATCH] Fixed FluidSynth support and added a default soundfont path on Linux --- README.txt | 22 ++++++++++++-------- mixer.c | 11 ---------- music.c | 51 ++++++++++++++++++++++++++++++++++++++++------ music.h | 1 - music_fluidsynth.c | 4 ++-- 5 files changed, 61 insertions(+), 28 deletions(-) diff --git a/README.txt b/README.txt index 9edc9694..e1c92eba 100644 --- a/README.txt +++ b/README.txt @@ -6,17 +6,17 @@ http://www.libsdl.org/projects/SDL_mixer/ Due to popular demand, here is a simple multi-channel audio mixer. It supports 8 channels of 16 bit stereo audio, plus a single channel -of music, mixed by the popular MikMod MOD, Timidity MIDI and SMPEG MP3 -libraries. +of music. See the header file SDL_mixer.h and the examples playwave.c and playmus.c for documentation on this mixer library. The mixer can currently load Microsoft WAVE files and Creative Labs VOC -files as audio samples, and can load MIDI files via Timidity and the -following music formats via MikMod: .MOD .S3M .IT .XM. It can load -Ogg Vorbis streams as music if built with Ogg Vorbis or Tremor libraries, -and finally it can load MP3 music using the SMPEG or libmad libraries. +files as audio samples, it can load FLAC files with libFLAC, it can load +Ogg Vorbis files with Ogg Vorbis or Tremor libraries, it can load MP3 files +using mpg123, SMPEG or libmad, and it can load MIDI files with Timidity, +FluidSynth, and natively on Windows, Mac OSX, and Linux, and finally it can +load the following file formats via ModPlug or MikMod: .MOD .S3M .IT .XM. Tremor decoding is disabled by default; you can enable it by passing --enable-music-ogg-tremor @@ -34,8 +34,14 @@ The process of mixing MIDI files to wave output is very CPU intensive, so if playing regular WAVE files sound great, but playing MIDI files sound choppy, try using 8-bit audio, mono audio, or lower frequencies. -To play MIDI files, you'll need to get a complete set of GUS patches -from: +To play MIDI files using FluidSynth, you'll need to set the SDL_SOUNDFONTS +environment variable to a Sound Font 2 (.sf2) file containing the musical +instruments you want to use for MIDI playback. +(On some Linux distributions you can install the fluid-soundfont-gm package) + + +To play MIDI files using Timidity, you'll need to get a complete set of +GUS patches from: http://www.libsdl.org/projects/mixer/timidity/timidity.tar.gz and unpack them in /usr/local/lib under UNIX, and C:\ under Win32. diff --git a/mixer.c b/mixer.c index 38eb461b..09f4a46a 100644 --- a/mixer.c +++ b/mixer.c @@ -140,12 +140,6 @@ int Mix_Init(int flags) { int result = 0; -#ifdef MIX_INIT_SOUNDFONT_PATHS - if (!soundfont_paths) { - soundfont_paths = SDL_strdup(MIX_INIT_SOUNDFONT_PATHS); - } -#endif - load_music(); if (flags & MIX_INIT_FLAC) { @@ -189,11 +183,6 @@ int Mix_Init(int flags) void Mix_Quit() { unload_music(); - - if (soundfont_paths) { - SDL_free(soundfont_paths); - soundfont_paths = NULL; - } } static int _Mix_remove_all_effects(int channel, effect_info **e); diff --git a/music.c b/music.c index d53bc65e..de65b1e8 100644 --- a/music.c +++ b/music.c @@ -66,7 +66,7 @@ static const char **music_decoders = NULL; static int num_decoders = 0; /* Semicolon-separated SoundFont paths */ -char* soundfont_paths = NULL; +static char* soundfont_paths = NULL; /* Interfaces for the various music interfaces, ordered by priority */ static Mix_MusicInterface *s_music_interfaces[] = @@ -297,6 +297,13 @@ int open_music(const SDL_AudioSpec *spec) int i; SDL_bool use_native_midi = SDL_FALSE; +#ifdef MIX_INIT_SOUNDFONT_PATHS + if (!soundfont_paths) { + soundfont_paths = SDL_strdup(MIX_INIT_SOUNDFONT_PATHS); + } +#endif + + #ifdef MUSIC_MID_NATIVE if (SDL_GetHintBoolean("SDL_NATIVE_MUSIC", SDL_FALSE) && native_midi_detect()) { use_native_midi = SDL_TRUE; @@ -929,9 +936,16 @@ void close_music(void) interface->opened = SDL_FALSE; } + if (soundfont_paths) { + SDL_free(soundfont_paths); + soundfont_paths = NULL; + } + /* rcg06042009 report available decoders at runtime. */ - SDL_free((void *)music_decoders); - music_decoders = NULL; + if (music_decoders) { + SDL_free((void *)music_decoders); + music_decoders = NULL; + } num_decoders = 0; ms_per_step = 0; @@ -972,11 +986,36 @@ int Mix_SetSoundFonts(const char *paths) const char* Mix_GetSoundFonts(void) { - if (!soundfont_paths || SDL_GetHintBoolean("SDL_FORCE_SOUNDFONTS", SDL_FALSE)) { - return SDL_getenv("SDL_SOUNDFONTS"); - } else { + const char *env_paths = SDL_getenv("SDL_SOUNDFONTS"); + SDL_bool force_env_paths = SDL_GetHintBoolean("SDL_FORCE_SOUNDFONTS", SDL_FALSE); + if (force_env_paths && (!env_paths || !*env_paths)) { + force_env_paths = SDL_FALSE; + } + if (soundfont_paths && *soundfont_paths && !force_env_paths) { return soundfont_paths; } + if (env_paths) { + return env_paths; + } + + /* We don't have any sound fonts set programmatically or in the environment + Time to start guessing where they might be... + */ + { + static char *s_soundfont_paths[] = { + "/usr/share/sounds/sf2/FluidR3_GM.sf2" /* Remember to add ',' here */ + }; + unsigned i; + + for (i = 0; i < SDL_arraysize(s_soundfont_paths); ++i) { + SDL_RWops *rwops = SDL_RWFromFile(s_soundfont_paths[i], "rb"); + if (rwops) { + SDL_RWclose(rwops); + return s_soundfont_paths[i]; + } + } + } + return NULL; } int Mix_EachSoundFont(int (*function)(const char*, void*), void *data) diff --git a/music.h b/music.h index 29bfa5bc..2239b1dc 100644 --- a/music.h +++ b/music.h @@ -117,7 +117,6 @@ extern void unload_music(void); extern char *music_cmd; extern SDL_AudioSpec music_spec; -extern char *soundfont_paths; #endif /* MUSIC_H_ */ diff --git a/music_fluidsynth.c b/music_fluidsynth.c index f87272ea..9f50e8f3 100644 --- a/music_fluidsynth.c +++ b/music_fluidsynth.c @@ -242,6 +242,7 @@ static SDL_bool FLUIDSYNTH_IsPlaying(void *context) static int FLUIDSYNTH_GetSome(void *context, void *data, int bytes, SDL_bool *done) { + FLUIDSYNTH_Music *music = (FLUIDSYNTH_Music *)context; int filled; filled = SDL_AudioStreamGet(music->stream, data, bytes); @@ -249,8 +250,7 @@ static int FLUIDSYNTH_GetSome(void *context, void *data, int bytes, SDL_bool *do return filled; } - /* FIXME: What happens at end of song? */ - if (fluidsynth.fluid_synth_write_s16(music->synth, mixer_spec.samples, music->buffer, 0, 2, music->buffer, 1, 2) != FLUID_OK) { + if (fluidsynth.fluid_synth_write_s16(music->synth, music_spec.samples, music->buffer, 0, 2, music->buffer, 1, 2) != FLUID_OK) { Mix_SetError("Error generating FluidSynth audio"); return -1; }