1.1 --- a/music_fluidsynth.c Fri Oct 20 21:55:03 2017 -0700
1.2 +++ b/music_fluidsynth.c Fri Oct 20 23:39:04 2017 -0700
1.3 @@ -117,14 +117,13 @@
1.4
1.5
1.6 typedef struct {
1.7 - SDL_AudioCVT convert;
1.8 fluid_synth_t *synth;
1.9 - fluid_player_t* player;
1.10 -} FluidSynthMidiSong;
1.11 + fluid_player_t *player;
1.12 + SDL_AudioStream *stream;
1.13 + void *buffer;
1.14 + int buffer_size;
1.15 +} FLUIDSYNTH_Music;
1.16
1.17 -static Uint16 format;
1.18 -static Uint8 channels;
1.19 -static int freq;
1.20
1.21 static int fluidsynth_check_soundfont(const char *path, void *data)
1.22 {
1.23 @@ -151,165 +150,134 @@
1.24 if (!Mix_EachSoundFont(fluidsynth_check_soundfont, NULL)) {
1.25 return -1;
1.26 }
1.27 -
1.28 - format = spec->format;
1.29 - channels = spec->channels;
1.30 - freq = spec->freq;
1.31 -
1.32 return 0;
1.33 }
1.34
1.35 -static FluidSynthMidiSong *fluidsynth_loadsong_common(int (*function)(FluidSynthMidiSong*, void*), void *data)
1.36 +static FLUIDSYNTH_Music *FLUIDSYNTH_LoadMusic(void *data)
1.37 {
1.38 - FluidSynthMidiSong *song;
1.39 - fluid_settings_t *settings = NULL;
1.40 + SDL_RWops *src = (SDL_RWops *)data;
1.41 + FLUIDSYNTH_Music *music;
1.42 + fluid_settings_t *settings;
1.43
1.44 - if ((song = SDL_calloc(1, sizeof(FluidSynthMidiSong)))) {
1.45 - if (SDL_BuildAudioCVT(&song->convert, AUDIO_S16, 2, freq, format, channels, freq) >= 0) {
1.46 - if ((settings = fluidsynth.new_fluid_settings())) {
1.47 - fluidsynth.fluid_settings_setnum(settings, "synth.sample-rate", (double) freq);
1.48 + if ((music = SDL_calloc(1, sizeof(FLUIDSYNTH_Music)))) {
1.49 + int channels = 2;
1.50 + if ((music->stream = SDL_NewAudioStream(AUDIO_S16SYS, channels, music_spec.freq, music_spec.format, music_spec.channels, music_spec.freq))) {
1.51 + music->buffer_size = music_spec.samples * sizeof(Sint16) * channels;
1.52 + if ((music->buffer = SDL_malloc(music->buffer_size))) {
1.53 + if ((settings = fluidsynth.new_fluid_settings())) {
1.54 + fluidsynth.fluid_settings_setnum(settings, "synth.sample-rate", (double) music_spec.freq);
1.55
1.56 - if ((song->synth = fluidsynth.new_fluid_synth(settings))) {
1.57 - if (Mix_EachSoundFont(fluidsynth_load_soundfont, (void*) song->synth)) {
1.58 - if ((song->player = fluidsynth.new_fluid_player(song->synth))) {
1.59 - if (function(song, data)) return song;
1.60 - fluidsynth.delete_fluid_player(song->player);
1.61 - } else {
1.62 - Mix_SetError("Failed to create FluidSynth player");
1.63 + if ((music->synth = fluidsynth.new_fluid_synth(settings))) {
1.64 + if (Mix_EachSoundFont(fluidsynth_load_soundfont, (void*) music->synth)) {
1.65 + if ((music->player = fluidsynth.new_fluid_player(music->synth))) {
1.66 + void *buffer;
1.67 + size_t size;
1.68 +
1.69 + buffer = SDL_LoadFile_RW(src, &size, SDL_FALSE);
1.70 + if (buffer) {
1.71 + if (fluidsynth.fluid_player_add_mem(music->player, buffer, size) == FLUID_OK) {
1.72 + SDL_free(buffer);
1.73 + return music;
1.74 + } else {
1.75 + Mix_SetError("FluidSynth failed to load in-memory song");
1.76 + }
1.77 + SDL_free(buffer);
1.78 + } else {
1.79 + SDL_OutOfMemory();
1.80 + }
1.81 + fluidsynth.delete_fluid_player(music->player);
1.82 + } else {
1.83 + Mix_SetError("Failed to create FluidSynth player");
1.84 + }
1.85 }
1.86 + fluidsynth.delete_fluid_synth(music->synth);
1.87 + } else {
1.88 + Mix_SetError("Failed to create FluidSynth synthesizer");
1.89 }
1.90 - fluidsynth.delete_fluid_synth(song->synth);
1.91 + fluidsynth.delete_fluid_settings(settings);
1.92 } else {
1.93 - Mix_SetError("Failed to create FluidSynth synthesizer");
1.94 + Mix_SetError("Failed to create FluidSynth settings");
1.95 }
1.96 - fluidsynth.delete_fluid_settings(settings);
1.97 } else {
1.98 - Mix_SetError("Failed to create FluidSynth settings");
1.99 + SDL_OutOfMemory();
1.100 }
1.101 - } else {
1.102 - Mix_SetError("Failed to set up audio conversion");
1.103 }
1.104 - SDL_free(song);
1.105 + SDL_free(music);
1.106 } else {
1.107 - Mix_SetError("Insufficient memory for song");
1.108 + SDL_OutOfMemory();
1.109 }
1.110 return NULL;
1.111 }
1.112
1.113 -static int fluidsynth_loadsong_RW_internal(FluidSynthMidiSong *song, void *data)
1.114 -{
1.115 - Sint64 offset;
1.116 - size_t size;
1.117 - char *buffer;
1.118 - SDL_RWops *src = (SDL_RWops*) data;
1.119 -
1.120 - offset = SDL_RWtell(src);
1.121 - SDL_RWseek(src, 0, RW_SEEK_END);
1.122 - size = (size_t)(SDL_RWtell(src) - offset);
1.123 - SDL_RWseek(src, offset, RW_SEEK_SET);
1.124 -
1.125 - if ((buffer = (char*) SDL_malloc(size))) {
1.126 - if(SDL_RWread(src, buffer, size, 1) == 1) {
1.127 - if (fluidsynth.fluid_player_add_mem(song->player, buffer, size) == FLUID_OK) {
1.128 - SDL_free(buffer);
1.129 - return 1;
1.130 - } else {
1.131 - Mix_SetError("FluidSynth failed to load in-memory song");
1.132 - }
1.133 - } else {
1.134 - Mix_SetError("Failed to read in-memory song");
1.135 - }
1.136 - SDL_free(buffer);
1.137 - } else {
1.138 - Mix_SetError("Insufficient memory for song");
1.139 - }
1.140 - return 0;
1.141 -}
1.142 -
1.143 static void *FLUIDSYNTH_CreateFromRW(SDL_RWops *src, int freesrc)
1.144 {
1.145 - FluidSynthMidiSong *song;
1.146 + FLUIDSYNTH_Music *music;
1.147
1.148 - song = fluidsynth_loadsong_common(fluidsynth_loadsong_RW_internal, (void*) src);
1.149 - if (song && freesrc) {
1.150 + music = FLUIDSYNTH_LoadMusic(src);
1.151 + if (music && freesrc) {
1.152 SDL_RWclose(src);
1.153 }
1.154 - return song;
1.155 + return music;
1.156 }
1.157
1.158 static void FLUIDSYNTH_SetVolume(void *context, int volume)
1.159 {
1.160 - FluidSynthMidiSong *song = (FluidSynthMidiSong *)context;
1.161 + FLUIDSYNTH_Music *music = (FLUIDSYNTH_Music *)context;
1.162 /* FluidSynth's default is 0.2. Make 1.2 the maximum. */
1.163 - fluidsynth.fluid_synth_set_gain(song->synth, (float) (volume * 1.2 / MIX_MAX_VOLUME));
1.164 + fluidsynth.fluid_synth_set_gain(music->synth, (float) (volume * 1.2 / MIX_MAX_VOLUME));
1.165 }
1.166
1.167 -static int FLUIDSYNTH_Play(void *context)
1.168 +static int FLUIDSYNTH_Play(void *context, int play_count)
1.169 {
1.170 - FluidSynthMidiSong *song = (FluidSynthMidiSong *)context;
1.171 - fluidsynth.fluid_player_set_loop(song->player, 1);
1.172 - fluidsynth.fluid_player_play(song->player);
1.173 + FLUIDSYNTH_Music *music = (FLUIDSYNTH_Music *)context;
1.174 + fluidsynth.fluid_player_set_loop(music->player, play_count);
1.175 + fluidsynth.fluid_player_play(music->player);
1.176 return 0;
1.177 }
1.178
1.179 static SDL_bool FLUIDSYNTH_IsPlaying(void *context)
1.180 {
1.181 - FluidSynthMidiSong *song = (FluidSynthMidiSong *)context;
1.182 - return fluidsynth.fluid_player_get_status(song->player) == FLUID_PLAYER_PLAYING ? SDL_TRUE : SDL_FALSE;
1.183 + FLUIDSYNTH_Music *music = (FLUIDSYNTH_Music *)context;
1.184 + return fluidsynth.fluid_player_get_status(music->player) == FLUID_PLAYER_PLAYING ? SDL_TRUE : SDL_FALSE;
1.185 }
1.186
1.187 +static int FLUIDSYNTH_GetSome(void *context, void *data, int bytes, SDL_bool *done)
1.188 +{
1.189 + int filled;
1.190 +
1.191 + filled = SDL_AudioStreamGet(music->stream, data, bytes);
1.192 + if (filled != 0) {
1.193 + return filled;
1.194 + }
1.195 +
1.196 + /* FIXME: What happens at end of song? */
1.197 + if (fluidsynth.fluid_synth_write_s16(music->synth, mixer_spec.samples, music->buffer, 0, 2, music->buffer, 1, 2) != FLUID_OK) {
1.198 + Mix_SetError("Error generating FluidSynth audio");
1.199 + return -1;
1.200 + }
1.201 + if (SDL_AudioStreamPut(music->stream, music->buffer, music->buffer_size) < 0) {
1.202 + return -1;
1.203 + }
1.204 + return 0;
1.205 +}
1.206 static int FLUIDSYNTH_GetAudio(void *context, void *data, int bytes)
1.207 {
1.208 - int result = -1;
1.209 - int frames = bytes / channels / ((format & 0xFF) / 8);
1.210 - int src_len = frames * 4; /* 16-bit stereo */
1.211 - void *src = dest;
1.212 -
1.213 - if (bytes < src_len) {
1.214 - if (!(src = SDL_malloc(src_len))) {
1.215 - Mix_SetError("Insufficient memory for audio conversion");
1.216 - return result;
1.217 - }
1.218 - }
1.219 -
1.220 - if (fluidsynth.fluid_synth_write_s16(song->synth, frames, src, 0, 2, src, 1, 2) != FLUID_OK) {
1.221 - Mix_SetError("Error generating FluidSynth audio");
1.222 - goto finish;
1.223 - }
1.224 -
1.225 - song->convert.buf = src;
1.226 - song->convert.len = src_len;
1.227 -
1.228 - if (SDL_ConvertAudio(&song->convert) < 0) {
1.229 - Mix_SetError("Error during audio conversion");
1.230 - goto finish;
1.231 - }
1.232 -
1.233 - if (src != dest)
1.234 - SDL_memcpy(dest, src, bytes);
1.235 -
1.236 - result = 0;
1.237 -
1.238 -finish:
1.239 - if (src != dest)
1.240 - SDL_free(src);
1.241 -
1.242 - return result;
1.243 + return music_pcm_getaudio(context, data, bytes, MIX_MAX_VOLUME, FLUIDSYNTH_GetSome);
1.244 }
1.245
1.246 static void FLUIDSYNTH_Stop(void *context)
1.247 {
1.248 - FluidSynthMidiSong *song = (FluidSynthMidiSong *)context;
1.249 - fluidsynth.fluid_player_stop(song->player);
1.250 + FLUIDSYNTH_Music *music = (FLUIDSYNTH_Music *)context;
1.251 + fluidsynth.fluid_player_stop(music->player);
1.252 }
1.253
1.254 static void FLUIDSYNTH_Delete(void *context)
1.255 {
1.256 - FluidSynthMidiSong *song = (FluidSynthMidiSong *)context;
1.257 - fluidsynth.delete_fluid_player(song->player);
1.258 - fluidsynth.delete_fluid_settings(fluidsynth.fluid_synth_get_settings(song->synth));
1.259 - fluidsynth.delete_fluid_synth(song->synth);
1.260 - SDL_free(song);
1.261 + FLUIDSYNTH_Music *music = (FLUIDSYNTH_Music *)context;
1.262 + fluidsynth.delete_fluid_player(music->player);
1.263 + fluidsynth.delete_fluid_settings(fluidsynth.fluid_synth_get_settings(music->synth));
1.264 + fluidsynth.delete_fluid_synth(music->synth);
1.265 + SDL_free(music);
1.266 }
1.267
1.268 Mix_MusicInterface Mix_MusicInterface_FLUIDSYNTH =