Switched to using SDL_AudioStream in SDL 2.0.7 for better streaming resampling support
authorSam Lantinga <slouken@libsdl.org>
Fri, 20 Oct 2017 23:39:04 -0700
changeset 797b4b6adff699a
parent 796 6287bc83c1b3
child 798 9b6d7d1b3a23
Switched to using SDL_AudioStream in SDL 2.0.7 for better streaming resampling support
Also made the following changes:
* Moved looping support into the music interfaces for better seamless looping when resampling
* Music interfaces always start play from the beginning of the song
* Implemented 24-bit and surround sound support for FLAC audio files
* Implemented sample dithering in MAD music interface using GPL code
* Improved error checking in music interfaces
CHANGES.txt
configure
configure.in
mixer.c
music.c
music.h
music_cmd.c
music_flac.c
music_fluidsynth.c
music_mad.c
music_mikmod.c
music_modplug.c
music_mpg123.c
music_nativemidi.c
music_ogg.c
music_smpeg.c
music_timidity.c
music_wav.c
     1.1 --- a/CHANGES.txt	Fri Oct 20 21:55:03 2017 -0700
     1.2 +++ b/CHANGES.txt	Fri Oct 20 23:39:04 2017 -0700
     1.3 @@ -1,4 +1,6 @@
     1.4  2.0.2:
     1.5 +Sam Lantinga - Fri Oct 20 22:04:50 PDT 2017
     1.6 + * Implemented 24-bit and surround sound support for FLAC audio files
     1.7  Sam Lantinga - Thu Oct 12 21:32:44 PDT 2017
     1.8   * Updated external libraries flac-1.3.2, libmodplug-0.8.9.0, libogg-1.3.2 and libvorbis-1.3.5
     1.9  Ryan Gordon - Thu Oct 12 21:29:59 PDT 2017
     2.1 --- a/configure	Fri Oct 20 21:55:03 2017 -0700
     2.2 +++ b/configure	Fri Oct 20 23:39:04 2017 -0700
     2.3 @@ -919,6 +919,7 @@
     2.4  with_smpeg_exec_prefix
     2.5  enable_smpegtest
     2.6  enable_music_mp3_mad_gpl
     2.7 +enable_music_mp3_mad_gpl_dithering
     2.8  enable_music_mp3_mpg123
     2.9  enable_music_mp3_mpg123_shared
    2.10  '
    2.11 @@ -1591,6 +1592,8 @@
    2.12    --disable-smpegtest     Do not try to compile and run a test SMPEG program
    2.13    --enable-music-mp3-mad-gpl
    2.14                            enable MP3 music via libmad GPL code [[default=no]]
    2.15 +  --enable-music-mp3-mad-gpl-dithering
    2.16 +                          enable MP3 music via libmad GPL code [[default=yes]]
    2.17    --enable-music-mp3-mpg123
    2.18                            enable MP3 music via libmpg123 [[default=yes]]
    2.19    --enable-music-mp3-mpg123-shared
    2.20 @@ -3927,13 +3930,13 @@
    2.21  else
    2.22    lt_cv_nm_interface="BSD nm"
    2.23    echo "int some_variable = 0;" > conftest.$ac_ext
    2.24 -  (eval echo "\"\$as_me:3930: $ac_compile\"" >&5)
    2.25 +  (eval echo "\"\$as_me:3933: $ac_compile\"" >&5)
    2.26    (eval "$ac_compile" 2>conftest.err)
    2.27    cat conftest.err >&5
    2.28 -  (eval echo "\"\$as_me:3933: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
    2.29 +  (eval echo "\"\$as_me:3936: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
    2.30    (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
    2.31    cat conftest.err >&5
    2.32 -  (eval echo "\"\$as_me:3936: output\"" >&5)
    2.33 +  (eval echo "\"\$as_me:3939: output\"" >&5)
    2.34    cat conftest.out >&5
    2.35    if $GREP 'External.*some_variable' conftest.out > /dev/null; then
    2.36      lt_cv_nm_interface="MS dumpbin"
    2.37 @@ -5144,7 +5147,7 @@
    2.38    ;;
    2.39  *-*-irix6*)
    2.40    # Find out which ABI we are using.
    2.41 -  echo '#line 5147 "configure"' > conftest.$ac_ext
    2.42 +  echo '#line 5150 "configure"' > conftest.$ac_ext
    2.43    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
    2.44    (eval $ac_compile) 2>&5
    2.45    ac_status=$?
    2.46 @@ -6974,11 +6977,11 @@
    2.47     -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    2.48     -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    2.49     -e 's:$: $lt_compiler_flag:'`
    2.50 -   (eval echo "\"\$as_me:6977: $lt_compile\"" >&5)
    2.51 +   (eval echo "\"\$as_me:6980: $lt_compile\"" >&5)
    2.52     (eval "$lt_compile" 2>conftest.err)
    2.53     ac_status=$?
    2.54     cat conftest.err >&5
    2.55 -   echo "$as_me:6981: \$? = $ac_status" >&5
    2.56 +   echo "$as_me:6984: \$? = $ac_status" >&5
    2.57     if (exit $ac_status) && test -s "$ac_outfile"; then
    2.58       # The compiler can only warn and ignore the option if not recognized
    2.59       # So say no if there are warnings other than the usual output.
    2.60 @@ -7313,11 +7316,11 @@
    2.61     -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    2.62     -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    2.63     -e 's:$: $lt_compiler_flag:'`
    2.64 -   (eval echo "\"\$as_me:7316: $lt_compile\"" >&5)
    2.65 +   (eval echo "\"\$as_me:7319: $lt_compile\"" >&5)
    2.66     (eval "$lt_compile" 2>conftest.err)
    2.67     ac_status=$?
    2.68     cat conftest.err >&5
    2.69 -   echo "$as_me:7320: \$? = $ac_status" >&5
    2.70 +   echo "$as_me:7323: \$? = $ac_status" >&5
    2.71     if (exit $ac_status) && test -s "$ac_outfile"; then
    2.72       # The compiler can only warn and ignore the option if not recognized
    2.73       # So say no if there are warnings other than the usual output.
    2.74 @@ -7418,11 +7421,11 @@
    2.75     -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    2.76     -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    2.77     -e 's:$: $lt_compiler_flag:'`
    2.78 -   (eval echo "\"\$as_me:7421: $lt_compile\"" >&5)
    2.79 +   (eval echo "\"\$as_me:7424: $lt_compile\"" >&5)
    2.80     (eval "$lt_compile" 2>out/conftest.err)
    2.81     ac_status=$?
    2.82     cat out/conftest.err >&5
    2.83 -   echo "$as_me:7425: \$? = $ac_status" >&5
    2.84 +   echo "$as_me:7428: \$? = $ac_status" >&5
    2.85     if (exit $ac_status) && test -s out/conftest2.$ac_objext
    2.86     then
    2.87       # The compiler can only warn and ignore the option if not recognized
    2.88 @@ -7473,11 +7476,11 @@
    2.89     -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    2.90     -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    2.91     -e 's:$: $lt_compiler_flag:'`
    2.92 -   (eval echo "\"\$as_me:7476: $lt_compile\"" >&5)
    2.93 +   (eval echo "\"\$as_me:7479: $lt_compile\"" >&5)
    2.94     (eval "$lt_compile" 2>out/conftest.err)
    2.95     ac_status=$?
    2.96     cat out/conftest.err >&5
    2.97 -   echo "$as_me:7480: \$? = $ac_status" >&5
    2.98 +   echo "$as_me:7483: \$? = $ac_status" >&5
    2.99     if (exit $ac_status) && test -s out/conftest2.$ac_objext
   2.100     then
   2.101       # The compiler can only warn and ignore the option if not recognized
   2.102 @@ -9842,7 +9845,7 @@
   2.103    lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   2.104    lt_status=$lt_dlunknown
   2.105    cat > conftest.$ac_ext <<_LT_EOF
   2.106 -#line 9845 "configure"
   2.107 +#line 9848 "configure"
   2.108  #include "confdefs.h"
   2.109  
   2.110  #if HAVE_DLFCN_H
   2.111 @@ -9938,7 +9941,7 @@
   2.112    lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   2.113    lt_status=$lt_dlunknown
   2.114    cat > conftest.$ac_ext <<_LT_EOF
   2.115 -#line 9941 "configure"
   2.116 +#line 9944 "configure"
   2.117  #include "confdefs.h"
   2.118  
   2.119  #if HAVE_DLFCN_H
   2.120 @@ -11158,7 +11161,7 @@
   2.121      done
   2.122  }
   2.123  
   2.124 -SDL_VERSION=2.0.0
   2.125 +SDL_VERSION=2.0.7
   2.126  
   2.127  
   2.128  if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
   2.129 @@ -12851,6 +12854,13 @@
   2.130    enable_music_mp3_mad_gpl=no
   2.131  fi
   2.132  
   2.133 +# Check whether --enable-music-mp3-mad-gpl-dithering was given.
   2.134 +if test "${enable_music_mp3_mad_gpl_dithering+set}" = set; then :
   2.135 +  enableval=$enable_music_mp3_mad_gpl_dithering;
   2.136 +else
   2.137 +  enable_music_mp3_mad_gpl_dithering=yes
   2.138 +fi
   2.139 +
   2.140  if test x$enable_music_mp3 = xyes -a x$enable_music_mp3_mad_gpl = xyes; then
   2.141      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libmad headers" >&5
   2.142  $as_echo_n "checking for libmad headers... " >&6; }
   2.143 @@ -12879,6 +12889,11 @@
   2.144  $as_echo "$have_libmad" >&6; }
   2.145      if test x$have_libmad = xyes; then
   2.146          EXTRA_CFLAGS="$EXTRA_CFLAGS -DMUSIC_MP3_MAD"
   2.147 +		if test x$enable_music_mp3_mad_gpl_dithering = xyes; then
   2.148 +            { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Using GPL libmad and MP3 dithering routines, this build of SDL_mixer is now under the GPL" >&5
   2.149 +$as_echo "$as_me: WARNING: *** Using GPL libmad and MP3 dithering routines, this build of SDL_mixer is now under the GPL" >&2;}
   2.150 +			EXTRA_CFLAGS="$EXTRA_CFLAGS -DMUSIC_MP3_MAD_GPL_DITHERING"
   2.151 +        fi
   2.152          EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lmad"
   2.153      else
   2.154          { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Unable to find MAD library (http://www.underbit.com/products/mad/)" >&5
     3.1 --- a/configure.in	Fri Oct 20 21:55:03 2017 -0700
     3.2 +++ b/configure.in	Fri Oct 20 23:39:04 2017 -0700
     3.3 @@ -188,7 +188,7 @@
     3.4  }
     3.5  
     3.6  dnl Check for SDL
     3.7 -SDL_VERSION=2.0.0
     3.8 +SDL_VERSION=2.0.7
     3.9  AM_PATH_SDL2($SDL_VERSION,
    3.10              :,
    3.11              AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!])
    3.12 @@ -608,6 +608,9 @@
    3.13  AC_ARG_ENABLE(music-mp3-mad-gpl,
    3.14  AC_HELP_STRING([--enable-music-mp3-mad-gpl], [enable MP3 music via libmad GPL code [[default=no]]]),
    3.15                    [], [enable_music_mp3_mad_gpl=no])
    3.16 +AC_ARG_ENABLE(music-mp3-mad-gpl-dithering,
    3.17 +AC_HELP_STRING([--enable-music-mp3-mad-gpl-dithering], [enable MP3 music via libmad GPL code [[default=yes]]]),
    3.18 +                  [], [enable_music_mp3_mad_gpl_dithering=yes])
    3.19  if test x$enable_music_mp3 = xyes -a x$enable_music_mp3_mad_gpl = xyes; then
    3.20      AC_MSG_CHECKING(for libmad headers)
    3.21      have_libmad=no
    3.22 @@ -620,6 +623,10 @@
    3.23      AC_MSG_RESULT($have_libmad)
    3.24      if test x$have_libmad = xyes; then
    3.25          EXTRA_CFLAGS="$EXTRA_CFLAGS -DMUSIC_MP3_MAD"
    3.26 +		if test x$enable_music_mp3_mad_gpl_dithering = xyes; then
    3.27 +            AC_MSG_WARN([*** Using GPL libmad and MP3 dithering routines, this build of SDL_mixer is now under the GPL])
    3.28 +			EXTRA_CFLAGS="$EXTRA_CFLAGS -DMUSIC_MP3_MAD_GPL_DITHERING"
    3.29 +        fi
    3.30          EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lmad"
    3.31      else
    3.32          AC_MSG_WARN([*** Unable to find MAD library (http://www.underbit.com/products/mad/)])
     4.1 --- a/mixer.c	Fri Oct 20 21:55:03 2017 -0700
     4.2 +++ b/mixer.c	Fri Oct 20 23:39:04 2017 -0700
     4.3 @@ -259,9 +259,7 @@
     4.4  #endif
     4.5  
     4.6      /* Mix the music (must be done before the channels are added) */
     4.7 -    if (music_active || (mix_music != music_mixer)) {
     4.8 -        mix_music(music_data, stream, len);
     4.9 -    }
    4.10 +    mix_music(music_data, stream, len);
    4.11  
    4.12      /* Mix any playing channels... */
    4.13      sdl_ticks = SDL_GetTicks();
    4.14 @@ -548,7 +546,6 @@
    4.15      MusicFragment *first = NULL, *last = NULL, *fragment = NULL;
    4.16      int count = 0;
    4.17      int fragment_size;
    4.18 -    int original_volume;
    4.19  
    4.20      *spec = mixer;
    4.21  
    4.22 @@ -579,12 +576,6 @@
    4.23              break;
    4.24          }
    4.25  
    4.26 -        if (interface->api == MIX_MUSIC_SMPEG) {
    4.27 -            /* Uh oh, if SMPEG couldn't create anything, it freed the src */
    4.28 -            freesrc = SDL_FALSE;
    4.29 -            break;
    4.30 -        }
    4.31 -
    4.32          /* Reset the stream for the next decoder */
    4.33          SDL_RWseek(src, start, RW_SEEK_SET);
    4.34      }
    4.35 @@ -598,14 +589,9 @@
    4.36      }
    4.37  
    4.38      Mix_LockAudio();
    4.39 -    original_volume = music_volume;
    4.40 - 
    4.41 -    if (interface->SetVolume) {
    4.42 -        interface->SetVolume(music, MIX_MAX_VOLUME);
    4.43 -    }
    4.44  
    4.45      if (interface->Play) {
    4.46 -        interface->Play(music);
    4.47 +        interface->Play(music, 1);
    4.48  	}
    4.49      playing = SDL_TRUE;
    4.50  
    4.51 @@ -647,10 +633,6 @@
    4.52          interface->Stop(music);
    4.53      }
    4.54  
    4.55 -    if (interface->SetVolume) {
    4.56 -        interface->SetVolume(music, original_volume);
    4.57 -    }
    4.58 -
    4.59      if (music) {
    4.60          interface->Delete(music);
    4.61      }
     5.1 --- a/music.c	Fri Oct 20 21:55:03 2017 -0700
     5.2 +++ b/music.c	Fri Oct 20 23:39:04 2017 -0700
     5.3 @@ -43,10 +43,9 @@
     5.4  
     5.5  
     5.6  char *music_cmd = NULL;
     5.7 -int volatile music_active = 1;
     5.8 +static SDL_bool music_active = SDL_TRUE;
     5.9 +static int music_volume = MIX_MAX_VOLUME;
    5.10  static Mix_Music * volatile music_playing = NULL;
    5.11 -int music_loops = 0;
    5.12 -int music_volume = MIX_MAX_VOLUME;
    5.13  SDL_AudioSpec music_spec;
    5.14  
    5.15  struct _Mix_Music {
    5.16 @@ -57,7 +56,6 @@
    5.17      Mix_Fading fading;
    5.18      int fade_step;
    5.19      int fade_steps;
    5.20 -    int error;
    5.21  };
    5.22  
    5.23  /* Used to calculate fading steps */
    5.24 @@ -147,7 +145,7 @@
    5.25  /* Local low-level functions prototypes */
    5.26  static void music_internal_initialize_volume(void);
    5.27  static void music_internal_volume(int volume);
    5.28 -static int  music_internal_play(Mix_Music *music, double position);
    5.29 +static int  music_internal_play(Mix_Music *music, int play_count, double position);
    5.30  static int  music_internal_position(double position);
    5.31  static SDL_bool music_internal_playing(void);
    5.32  static void music_internal_halt(void);
    5.33 @@ -163,49 +161,46 @@
    5.34      Mix_UnlockAudio();
    5.35  }
    5.36  
    5.37 +/* Convenience function to fill audio and mix at the specified volume
    5.38 +   This is called from many music player's GetAudio callback.
    5.39 + */
    5.40 +int music_pcm_getaudio(void *context, void *data, int bytes, int volume,
    5.41 +                       int (*GetSome)(void *context, void *data, int bytes, SDL_bool *done))
    5.42 +{
    5.43 +    Uint8 *snd = (Uint8 *)data;
    5.44 +    Uint8 *dst;
    5.45 +    int len = bytes;
    5.46 +    SDL_bool done = SDL_FALSE;
    5.47  
    5.48 -/* If music isn't playing, halt it if no looping is required, restart it */
    5.49 -/* otherwise. NOP if the music is playing */
    5.50 -static int music_halt_or_loop(void)
    5.51 -{
    5.52 -    /* Restart music if it has to loop */
    5.53 -
    5.54 -    if (!music_internal_playing())
    5.55 -    {
    5.56 -        /* Native MIDI handles looping internally */
    5.57 -        if (music_playing->interface->api == MIX_MUSIC_NATIVEMIDI) {
    5.58 -            music_loops = 0;
    5.59 +    if (volume == MIX_MAX_VOLUME) {
    5.60 +        dst = snd;
    5.61 +    } else {
    5.62 +        dst = SDL_stack_alloc(Uint8, bytes);
    5.63 +    }
    5.64 +    while (len > 0 && !done) {
    5.65 +        int consumed = GetSome(context, dst, len, &done);
    5.66 +        if (consumed < 0) {
    5.67 +            break;
    5.68          }
    5.69  
    5.70 -        /* Restart music if it has to loop at a high level */
    5.71 -        if (music_loops)
    5.72 -        {
    5.73 -            Mix_Fading current_fade;
    5.74 -            if (music_loops > 0) {
    5.75 -                --music_loops;
    5.76 -            }
    5.77 -            current_fade = music_playing->fading;
    5.78 -            music_internal_play(music_playing, 0.0);
    5.79 -            music_playing->fading = current_fade;
    5.80 +        if (volume == MIX_MAX_VOLUME) {
    5.81 +            dst += consumed;
    5.82 +        } else {
    5.83 +            SDL_MixAudioFormat(snd, dst, music_spec.format, (Uint32)consumed, volume);
    5.84 +            snd += consumed;
    5.85          }
    5.86 -        else
    5.87 -        {
    5.88 -            music_internal_halt();
    5.89 -            if (music_finished_hook)
    5.90 -                music_finished_hook();
    5.91 -
    5.92 -            return 0;
    5.93 -        }
    5.94 +        len -= consumed;
    5.95      }
    5.96 -
    5.97 -    return 1;
    5.98 +    if (volume != MIX_MAX_VOLUME) {
    5.99 +        SDL_stack_free(dst);
   5.100 +    }
   5.101 +    return len;
   5.102  }
   5.103  
   5.104 -
   5.105  /* Mixing function */
   5.106  void music_mixer(void *udata, Uint8 *stream, int len)
   5.107  {
   5.108 -    if (music_playing && music_active) {
   5.109 +    while (music_playing && music_active && len > 0) {
   5.110          /* Handle fading */
   5.111          if (music_playing->fading != MIX_NO_FADING) {
   5.112              if (music_playing->fade_step++ < music_playing->fade_steps) {
   5.113 @@ -231,23 +226,26 @@
   5.114              }
   5.115          }
   5.116  
   5.117 -        music_halt_or_loop();
   5.118 -        if (!music_internal_playing()) {
   5.119 -            return;
   5.120 +        if (music_playing->interface->GetAudio) {
   5.121 +            int left = music_playing->interface->GetAudio(music_playing->context, stream, len);
   5.122 +            if (left != 0) {
   5.123 +                /* Either an error or finished playing with data left */
   5.124 +                music_playing->playing = SDL_FALSE;
   5.125 +            }
   5.126 +            if (left > 0) {
   5.127 +                stream += (len - left);
   5.128 +                len = left;
   5.129 +            } else {
   5.130 +                len = 0;
   5.131 +            }
   5.132 +        } else {
   5.133 +            len = 0;
   5.134          }
   5.135  
   5.136 -        if (music_playing->interface->GetAudio) {
   5.137 -            int left = music_playing->interface->GetAudio(music_playing->context, stream, len);
   5.138 -            if (left > 0) {
   5.139 -                music_playing->playing = SDL_FALSE;
   5.140 -            }
   5.141 -
   5.142 -            /* Handle seamless music looping */
   5.143 -            if (left > 0 && left < len) {
   5.144 -                music_halt_or_loop();
   5.145 -                if (music_internal_playing()) {
   5.146 -                    music_mixer(udata, stream+(len-left), left);
   5.147 -                }
   5.148 +        if (!music_internal_playing()) {
   5.149 +            music_internal_halt();
   5.150 +            if (music_finished_hook) {
   5.151 +                music_finished_hook();
   5.152              }
   5.153          }
   5.154      }
   5.155 @@ -523,12 +521,6 @@
   5.156              return music;
   5.157          }
   5.158  
   5.159 -        if (interface->api == MIX_MUSIC_SMPEG) {
   5.160 -            /* Uh oh, if SMPEG couldn't create a context, it freed the src */
   5.161 -            freesrc = SDL_FALSE;
   5.162 -            break;
   5.163 -        }
   5.164 -
   5.165          /* Reset the stream for the next decoder */
   5.166          SDL_RWseek(src, start, RW_SEEK_SET);
   5.167      }
   5.168 @@ -589,7 +581,7 @@
   5.169  
   5.170  /* Play a music chunk.  Returns 0, or -1 if there was an error.
   5.171   */
   5.172 -static int music_internal_play(Mix_Music *music, double position)
   5.173 +static int music_internal_play(Mix_Music *music, int play_count, double position)
   5.174  {
   5.175      int retval = 0;
   5.176  
   5.177 @@ -615,7 +607,7 @@
   5.178      music_internal_initialize_volume();
   5.179  
   5.180      /* Set up for playback */
   5.181 -    retval = music->interface->Play(music->context);
   5.182 +    retval = music->interface->Play(music->context, play_count);
   5.183  
   5.184      /* Set the playback position, note any errors if an offset is used */
   5.185      if (retval == 0) {
   5.186 @@ -631,6 +623,7 @@
   5.187  
   5.188      /* If the setup failed, we're not playing any music anymore */
   5.189      if (retval < 0) {
   5.190 +        music->playing = SDL_FALSE;
   5.191          music_playing = NULL;
   5.192      }
   5.193      return(retval);
   5.194 @@ -668,13 +661,11 @@
   5.195          SDL_Delay(100);
   5.196          Mix_LockAudio();
   5.197      }
   5.198 -    music_active = 1;
   5.199 -    if (loops == 1) {
   5.200 +    if (loops == 0) {
   5.201          /* Loop is the number of times to play the audio */
   5.202 -        loops = 0;
   5.203 +        loops = 1;
   5.204      }
   5.205 -    music_loops = loops;
   5.206 -    retval = music_internal_play(music, position);
   5.207 +    retval = music_internal_play(music, loops, position);
   5.208      Mix_UnlockAudio();
   5.209  
   5.210      return(retval);
   5.211 @@ -833,20 +824,24 @@
   5.212  void Mix_PauseMusic(void)
   5.213  {
   5.214      Mix_LockAudio();
   5.215 -    if (music_playing && music_playing->interface->Pause) {
   5.216 -        music_playing->interface->Pause(music_playing->context);
   5.217 +    if (music_playing) {
   5.218 +        if (music_playing->interface->Pause) {
   5.219 +            music_playing->interface->Pause(music_playing->context);
   5.220 +        }
   5.221      }
   5.222 -    music_active = 0;
   5.223 +    music_active = SDL_FALSE;
   5.224      Mix_UnlockAudio();
   5.225  }
   5.226  
   5.227  void Mix_ResumeMusic(void)
   5.228  {
   5.229      Mix_LockAudio();
   5.230 -    music_active = 1;
   5.231 -    if (music_playing && music_playing->interface->Resume) {
   5.232 -        music_playing->interface->Resume(music_playing->context);
   5.233 +    if (music_playing) {
   5.234 +        if (music_playing->interface->Resume) {
   5.235 +            music_playing->interface->Resume(music_playing->context);
   5.236 +        }
   5.237      }
   5.238 +    music_active = SDL_TRUE;
   5.239      Mix_UnlockAudio();
   5.240  }
   5.241  
   5.242 @@ -857,32 +852,30 @@
   5.243  
   5.244  int Mix_PausedMusic(void)
   5.245  {
   5.246 -    return (music_active == 0);
   5.247 +    return (music_active == SDL_FALSE);
   5.248  }
   5.249  
   5.250  /* Check the status of the music */
   5.251  static SDL_bool music_internal_playing(void)
   5.252  {
   5.253 -    if (music_playing == NULL) {
   5.254 +    if (!music_playing) {
   5.255          return SDL_FALSE;
   5.256      }
   5.257  
   5.258      if (music_playing->interface->IsPlaying) {
   5.259 -        return music_playing->interface->IsPlaying(music_playing->context);
   5.260 +        music_playing->playing = music_playing->interface->IsPlaying(music_playing->context);
   5.261      }
   5.262      return music_playing->playing;
   5.263  }
   5.264  int Mix_PlayingMusic(void)
   5.265  {
   5.266 -    int playing = 0;
   5.267 +    SDL_bool playing;
   5.268  
   5.269      Mix_LockAudio();
   5.270 -    if (music_playing) {
   5.271 -        playing = music_loops || music_internal_playing();
   5.272 -    }
   5.273 +    playing = music_internal_playing();
   5.274      Mix_UnlockAudio();
   5.275  
   5.276 -    return(playing);
   5.277 +    return playing ? 1 : 0;
   5.278  }
   5.279  
   5.280  /* Set the external music playback command */
     6.1 --- a/music.h	Fri Oct 20 21:55:03 2017 -0700
     6.2 +++ b/music.h	Fri Oct 20 23:39:04 2017 -0700
     6.3 @@ -70,8 +70,8 @@
     6.4      /* Set the volume */
     6.5      void (*SetVolume)(void *music, int volume);
     6.6  
     6.7 -    /* Start playing music */
     6.8 -    int (*Play)(void *music);
     6.9 +    /* Start playing music from the beginning with an optional loop count */
    6.10 +    int (*Play)(void *music, int play_count);
    6.11  
    6.12      /* Returns SDL_TRUE if music is still playing */
    6.13      SDL_bool (*IsPlaying)(void *music);
    6.14 @@ -109,14 +109,13 @@
    6.15  extern Mix_MusicInterface *get_music_interface(int index);
    6.16  extern SDL_bool has_music(Mix_MusicType type);
    6.17  extern int open_music(const SDL_AudioSpec *spec);
    6.18 +extern int music_pcm_getaudio(void *context, void *data, int bytes, int volume,
    6.19 +                              int (*GetSome)(void *context, void *data, int bytes, SDL_bool *done));
    6.20  extern void music_mixer(void *udata, Uint8 *stream, int len);
    6.21  extern void close_music(void);
    6.22  extern void unload_music(void);
    6.23  
    6.24  extern char *music_cmd;
    6.25 -extern int volatile music_active;
    6.26 -extern int music_loops;
    6.27 -extern int music_volume;
    6.28  extern SDL_AudioSpec music_spec;
    6.29  extern char *soundfont_paths;
    6.30  
     7.1 --- a/music_cmd.c	Fri Oct 20 21:55:03 2017 -0700
     7.2 +++ b/music_cmd.c	Fri Oct 20 23:39:04 2017 -0700
     7.3 @@ -44,6 +44,7 @@
     7.4      char *file;
     7.5      char *cmd;
     7.6      pid_t pid;
     7.7 +    int play_count;
     7.8  } MusicCMD;
     7.9  
    7.10  
    7.11 @@ -148,10 +149,11 @@
    7.12  }
    7.13  
    7.14  /* Start playback of a given music stream */
    7.15 -static int MusicCMD_Play(void *context)
    7.16 +static int MusicCMD_Play(void *context, int play_count)
    7.17  {
    7.18      MusicCMD *music = (MusicCMD *)context;
    7.19  
    7.20 +    music->play_count = play_count;
    7.21  #ifdef HAVE_FORK
    7.22      music->pid = fork();
    7.23  #else
    7.24 @@ -204,6 +206,16 @@
    7.25          if (kill(music->pid, 0) == 0) {
    7.26              return SDL_TRUE;
    7.27          }
    7.28 +
    7.29 +        /* We might want to loop */
    7.30 +        if (music->play_count != 1) {
    7.31 +            int play_count = -1;
    7.32 +            if (music->play_count > 0) {
    7.33 +                play_count = (music->play_count - 1);
    7.34 +            }
    7.35 +            MusicCMD_Play(music, play_count);
    7.36 +            return SDL_TRUE;
    7.37 +        }
    7.38      }
    7.39      return SDL_FALSE;
    7.40  }
     8.1 --- a/music_flac.c	Fri Oct 20 21:55:03 2017 -0700
     8.2 +++ b/music_flac.c	Fri Oct 20 23:39:04 2017 -0700
     8.3 @@ -24,6 +24,7 @@
     8.4  
     8.5  #ifdef MUSIC_FLAC
     8.6  
     8.7 +#include "SDL_assert.h"
     8.8  #include "SDL_loadso.h"
     8.9  
    8.10  #include "music_flac.h"
    8.11 @@ -188,7 +189,7 @@
    8.12              Mix_SetError("Missing FLAC.framework");
    8.13              return -1;
    8.14          }
    8.15 -#endif // __MACOSX__
    8.16 +#endif /* __MACOSX__ */
    8.17  
    8.18          flac.FLAC__stream_decoder_new = FLAC__stream_decoder_new;
    8.19          flac.FLAC__stream_decoder_delete = FLAC__stream_decoder_delete;
    8.20 @@ -226,51 +227,35 @@
    8.21  
    8.22  
    8.23  typedef struct {
    8.24 -    FLAC__uint64 sample_size;
    8.25 +    int volume;
    8.26 +    int play_count;
    8.27 +    FLAC__StreamDecoder *flac_decoder;
    8.28      unsigned sample_rate;
    8.29      unsigned channels;
    8.30      unsigned bits_per_sample;
    8.31 -    FLAC__uint64 total_samples;
    8.32 -
    8.33 -    // the following are used to handle the callback nature of the writer
    8.34 -    int max_to_read;
    8.35 -    char *data;             // pointer to beginning of data array
    8.36 -    int data_len;           // size of data array
    8.37 -    int data_read;          // amount of data array used
    8.38 -    char *overflow;         // pointer to beginning of overflow array
    8.39 -    int overflow_len;       // size of overflow array
    8.40 -    int overflow_read;      // amount of overflow array used
    8.41 -} FLAC_Data;
    8.42 -
    8.43 -typedef struct {
    8.44 -    SDL_bool playing;
    8.45 -    int volume;
    8.46 -    int section;
    8.47 -    FLAC__StreamDecoder *flac_decoder;
    8.48 -    FLAC_Data flac_data;
    8.49      SDL_RWops *src;
    8.50      int freesrc;
    8.51 -    SDL_AudioCVT cvt;
    8.52 -    int len_available;
    8.53 -    Uint8 *snd_available;
    8.54 -} FLAC_music;
    8.55 +    SDL_AudioStream *stream;
    8.56 +} FLAC_Music;
    8.57  
    8.58  
    8.59 +static int FLAC_Seek(void *context, double position);
    8.60 +
    8.61  static FLAC__StreamDecoderReadStatus flac_read_music_cb(
    8.62                                      const FLAC__StreamDecoder *decoder,
    8.63                                      FLAC__byte buffer[],
    8.64                                      size_t *bytes,
    8.65                                      void *client_data)
    8.66  {
    8.67 -    FLAC_music *data = (FLAC_music*)client_data;
    8.68 +    FLAC_Music *data = (FLAC_Music*)client_data;
    8.69  
    8.70 -    // make sure there is something to be reading
    8.71 +    /* make sure there is something to be reading */
    8.72      if (*bytes > 0) {
    8.73          *bytes = SDL_RWread (data->src, buffer, sizeof (FLAC__byte), *bytes);
    8.74  
    8.75 -        if (*bytes == 0) { // error or no data was read (EOF)
    8.76 +        if (*bytes == 0) { /* error or no data was read (EOF) */
    8.77              return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
    8.78 -        } else { // data was read, continue
    8.79 +        } else { /* data was read, continue */
    8.80              return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
    8.81          }
    8.82      } else {
    8.83 @@ -283,9 +268,9 @@
    8.84                                      FLAC__uint64 absolute_byte_offset,
    8.85                                      void *client_data)
    8.86  {
    8.87 -    FLAC_music *data = (FLAC_music*)client_data;
    8.88 +    FLAC_Music *data = (FLAC_Music*)client_data;
    8.89  
    8.90 -    if (SDL_RWseek (data->src, absolute_byte_offset, RW_SEEK_SET) < 0) {
    8.91 +    if (SDL_RWseek(data->src, absolute_byte_offset, RW_SEEK_SET) < 0) {
    8.92          return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
    8.93      } else {
    8.94          return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
    8.95 @@ -297,9 +282,9 @@
    8.96                                      FLAC__uint64 *absolute_byte_offset,
    8.97                                      void *client_data)
    8.98  {
    8.99 -    FLAC_music *data = (FLAC_music*)client_data;
   8.100 +    FLAC_Music *data = (FLAC_Music*)client_data;
   8.101  
   8.102 -    Sint64 pos = SDL_RWtell (data->src);
   8.103 +    Sint64 pos = SDL_RWtell(data->src);
   8.104  
   8.105      if (pos < 0) {
   8.106          return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
   8.107 @@ -309,17 +294,17 @@
   8.108      }
   8.109  }
   8.110  
   8.111 -static FLAC__StreamDecoderLengthStatus flac_length_music_cb (
   8.112 +static FLAC__StreamDecoderLengthStatus flac_length_music_cb(
   8.113                                      const FLAC__StreamDecoder *decoder,
   8.114                                      FLAC__uint64 *stream_length,
   8.115                                      void *client_data)
   8.116  {
   8.117 -    FLAC_music *data = (FLAC_music*)client_data;
   8.118 +    FLAC_Music *data = (FLAC_Music*)client_data;
   8.119  
   8.120 -    Sint64 pos = SDL_RWtell (data->src);
   8.121 -    Sint64 length = SDL_RWseek (data->src, 0, RW_SEEK_END);
   8.122 +    Sint64 pos = SDL_RWtell(data->src);
   8.123 +    Sint64 length = SDL_RWseek(data->src, 0, RW_SEEK_END);
   8.124  
   8.125 -    if (SDL_RWseek (data->src, pos, RW_SEEK_SET) != pos || length < 0) {
   8.126 +    if (SDL_RWseek(data->src, pos, RW_SEEK_SET) != pos || length < 0) {
   8.127          /* there was an error attempting to return the stream to the original
   8.128           * position, or the length was invalid. */
   8.129          return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
   8.130 @@ -333,18 +318,18 @@
   8.131                                  const FLAC__StreamDecoder *decoder,
   8.132                                  void *client_data)
   8.133  {
   8.134 -    FLAC_music *data = (FLAC_music*)client_data;
   8.135 +    FLAC_Music *data = (FLAC_Music*)client_data;
   8.136  
   8.137 -    Sint64 pos = SDL_RWtell (data->src);
   8.138 -    Sint64 end = SDL_RWseek (data->src, 0, RW_SEEK_END);
   8.139 +    Sint64 pos = SDL_RWtell(data->src);
   8.140 +    Sint64 end = SDL_RWseek(data->src, 0, RW_SEEK_END);
   8.141  
   8.142 -    // was the original position equal to the end (a.k.a. the seek didn't move)?
   8.143 +    /* was the original position equal to the end (a.k.a. the seek didn't move)? */
   8.144      if (pos == end) {
   8.145 -        // must be EOF
   8.146 +        /* must be EOF */
   8.147          return true;
   8.148      } else {
   8.149 -        // not EOF, return to the original position
   8.150 -        SDL_RWseek (data->src, pos, RW_SEEK_SET);
   8.151 +        /* not EOF, return to the original position */
   8.152 +        SDL_RWseek(data->src, pos, RW_SEEK_SET);
   8.153          return false;
   8.154      }
   8.155  }
   8.156 @@ -355,96 +340,81 @@
   8.157                                      const FLAC__int32 *const buffer[],
   8.158                                      void *client_data)
   8.159  {
   8.160 -    FLAC_music *data = (FLAC_music *)client_data;
   8.161 -    size_t i;
   8.162 +    FLAC_Music *music = (FLAC_Music *)client_data;
   8.163 +    Sint16 *data;
   8.164 +    int i, j, channels;
   8.165 +    int shift_amount = 0;
   8.166  
   8.167 -    if (data->flac_data.total_samples == 0) {
   8.168 -        SDL_SetError ("Given FLAC file does not specify its sample count.");
   8.169 +    if (!music->stream) {
   8.170          return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
   8.171      }
   8.172  
   8.173 -    if (data->flac_data.channels != 2 ||
   8.174 -        data->flac_data.bits_per_sample != 16) {
   8.175 -        SDL_SetError("Current FLAC support is only for 16 bit Stereo files.");
   8.176 +    switch (music->bits_per_sample) {
   8.177 +    case 16:
   8.178 +        shift_amount = 0;
   8.179 +        break;
   8.180 +    case 20:
   8.181 +        shift_amount = 4;
   8.182 +        break;
   8.183 +    case 24:
   8.184 +        shift_amount = 8;
   8.185 +        break;
   8.186 +    default:
   8.187 +        SDL_SetError("FLAC decoder doesn't support %d bits_per_sample", music->bits_per_sample);
   8.188          return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
   8.189      }
   8.190  
   8.191 -    for (i = 0; i < frame->header.blocksize; i++) {
   8.192 -        FLAC__int16 i16;
   8.193 -        FLAC__uint16 ui16;
   8.194 +    if (music->channels == 3) {
   8.195 +        /* We'll just drop the center channel for now */
   8.196 +        channels = 2;
   8.197 +    } else {
   8.198 +        channels = music->channels;
   8.199 +    }
   8.200  
   8.201 -        // make sure we still have at least two bytes that can be read (one for
   8.202 -        // each channel)
   8.203 -        if (data->flac_data.max_to_read >= 4) {
   8.204 -            // does the data block exist?
   8.205 -            if (!data->flac_data.data) {
   8.206 -                data->flac_data.data_len = data->flac_data.max_to_read;
   8.207 -                data->flac_data.data_read = 0;
   8.208 +    data = SDL_stack_alloc(Sint16, (frame->header.blocksize * channels));
   8.209 +    if (!data) {
   8.210 +        SDL_SetError("Couldn't allocate %d bytes stack memory", (int)(frame->header.blocksize * channels * sizeof(*data)));
   8.211 +        return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
   8.212 +    }
   8.213 +    if (music->channels == 3) {
   8.214 +        Sint16 *dst = data;
   8.215 +        for (i = 0; i < frame->header.blocksize; ++i) {
   8.216 +            Sint16 FL = (buffer[0][i] >> shift_amount);
   8.217 +            Sint16 FR = (buffer[1][i] >> shift_amount);
   8.218 +            Sint16 FCmix = (Sint16)((buffer[2][i] >> shift_amount) * 0.5f);
   8.219 +            int sample;
   8.220  
   8.221 -                // create it
   8.222 -                data->flac_data.data =
   8.223 -                    (char *)SDL_malloc (data->flac_data.data_len);
   8.224 +            sample = (FL + FCmix);
   8.225 +            if (sample > SDL_MAX_SINT16) {
   8.226 +                *dst = SDL_MAX_SINT16;
   8.227 +            } else if (sample < SDL_MIN_SINT16) {
   8.228 +                *dst = SDL_MIN_SINT16;
   8.229 +            } else {
   8.230 +                *dst = sample;
   8.231 +            }
   8.232 +            ++dst;
   8.233  
   8.234 -                if (!data->flac_data.data) {
   8.235 -                    return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
   8.236 -                }
   8.237 +            sample = (FR + FCmix);
   8.238 +            if (sample > SDL_MAX_SINT16) {
   8.239 +                *dst = SDL_MAX_SINT16;
   8.240 +            } else if (sample < SDL_MIN_SINT16) {
   8.241 +                *dst = SDL_MIN_SINT16;
   8.242 +            } else {
   8.243 +                *dst = sample;
   8.244              }
   8.245 -
   8.246 -            i16 = (FLAC__int16)buffer[0][i];
   8.247 -            ui16 = (FLAC__uint16)i16;
   8.248 -
   8.249 -            *((data->flac_data.data) + (data->flac_data.data_read++)) =
   8.250 -                                                            (char)(ui16);
   8.251 -            *((data->flac_data.data) + (data->flac_data.data_read++)) =
   8.252 -                                                            (char)(ui16 >> 8);
   8.253 -
   8.254 -            i16 = (FLAC__int16)buffer[1][i];
   8.255 -            ui16 = (FLAC__uint16)i16;
   8.256 -
   8.257 -            *((data->flac_data.data) + (data->flac_data.data_read++)) =
   8.258 -                                                            (char)(ui16);
   8.259 -            *((data->flac_data.data) + (data->flac_data.data_read++)) =
   8.260 -                                                            (char)(ui16 >> 8);
   8.261 -
   8.262 -            data->flac_data.max_to_read -= 4;
   8.263 -
   8.264 -            if (data->flac_data.max_to_read < 4) {
   8.265 -                // we need to set this so that the read halts from the
   8.266 -                // FLAC_getsome function.
   8.267 -                data->flac_data.max_to_read = 0;
   8.268 +            ++dst;
   8.269 +        }
   8.270 +    } else {
   8.271 +        for (i = 0; i < channels; ++i) {
   8.272 +            Sint16 *dst = data + i;
   8.273 +            for (j = 0; j < frame->header.blocksize; ++j) {
   8.274 +                *dst = (buffer[i][j] >> shift_amount);
   8.275 +                dst += channels;
   8.276              }
   8.277 -        } else {
   8.278 -            // we need to write to the overflow
   8.279 -            if (!data->flac_data.overflow) {
   8.280 -                data->flac_data.overflow_len = (int)(4 * (frame->header.blocksize - i));
   8.281 -                data->flac_data.overflow_read = 0;
   8.282 -
   8.283 -                // make it big enough for the rest of the block
   8.284 -                data->flac_data.overflow =
   8.285 -                    (char *)SDL_malloc (data->flac_data.overflow_len);
   8.286 -
   8.287 -                if (!data->flac_data.overflow) {
   8.288 -                    return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
   8.289 -                }
   8.290 -            }
   8.291 -
   8.292 -            i16 = (FLAC__int16)buffer[0][i];
   8.293 -            ui16 = (FLAC__uint16)i16;
   8.294 -
   8.295 -            *((data->flac_data.overflow) + (data->flac_data.overflow_read++)) =
   8.296 -                                                            (char)(ui16);
   8.297 -            *((data->flac_data.overflow) + (data->flac_data.overflow_read++)) =
   8.298 -                                                            (char)(ui16 >> 8);
   8.299 -
   8.300 -            i16 = (FLAC__int16)buffer[1][i];
   8.301 -            ui16 = (FLAC__uint16)i16;
   8.302 -
   8.303 -            *((data->flac_data.overflow) + (data->flac_data.overflow_read++)) =
   8.304 -                                                            (char)(ui16);
   8.305 -            *((data->flac_data.overflow) + (data->flac_data.overflow_read++)) =
   8.306 -                                                            (char)(ui16 >> 8);
   8.307          }
   8.308      }
   8.309 +    SDL_AudioStreamPut(music->stream, data, (frame->header.blocksize * channels * sizeof(*data)));
   8.310 +    SDL_stack_free(data);
   8.311  
   8.312      return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
   8.313  }
   8.314 @@ -454,18 +424,30 @@
   8.315                      const FLAC__StreamMetadata *metadata,
   8.316                      void *client_data)
   8.317  {
   8.318 -    FLAC_music *data = (FLAC_music *)client_data;
   8.319 +    FLAC_Music *music = (FLAC_Music *)client_data;
   8.320 +    int channels;
   8.321  
   8.322 -    if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
   8.323 -        data->flac_data.sample_rate = metadata->data.stream_info.sample_rate;
   8.324 -        data->flac_data.channels = metadata->data.stream_info.channels;
   8.325 -        data->flac_data.total_samples =
   8.326 -                            metadata->data.stream_info.total_samples;
   8.327 -        data->flac_data.bits_per_sample =
   8.328 -                            metadata->data.stream_info.bits_per_sample;
   8.329 -        data->flac_data.sample_size = data->flac_data.channels *
   8.330 -                                        ((data->flac_data.bits_per_sample) / 8);
   8.331 +    if (metadata->type != FLAC__METADATA_TYPE_STREAMINFO) {
   8.332 +        return;
   8.333      }
   8.334 +
   8.335 +    music->sample_rate = metadata->data.stream_info.sample_rate;
   8.336 +    music->channels = metadata->data.stream_info.channels;
   8.337 +    music->bits_per_sample = metadata->data.stream_info.bits_per_sample;
   8.338 +/*printf("FLAC: Sample rate = %d, channels = %d, bits_per_sample = %d\n", music->sample_rate, music->channels, music->bits_per_sample);*/
   8.339 +
   8.340 +    /* SDL's channel mapping and FLAC channel mapping are the same,
   8.341 +       except for 3 channels: SDL is FL FR LFE and FLAC is FL FR FC
   8.342 +     */
   8.343 +    if (music->channels == 3) {
   8.344 +        channels = 2;
   8.345 +    } else {
   8.346 +        channels = music->channels;
   8.347 +    }
   8.348 +    /* We check for NULL stream later when we get data */
   8.349 +    SDL_assert(!music->stream);
   8.350 +    music->stream = SDL_NewAudioStream(AUDIO_S16SYS, channels, music->sample_rate,
   8.351 +                                      music_spec.format, music_spec.channels, music_spec.freq);
   8.352  }
   8.353  
   8.354  static void flac_error_music_cb(
   8.355 @@ -473,22 +455,22 @@
   8.356                  FLAC__StreamDecoderErrorStatus status,
   8.357                  void *client_data)
   8.358  {
   8.359 -    // print an SDL error based on the error status
   8.360 +    /* print an SDL error based on the error status */
   8.361      switch (status) {
   8.362 -        case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
   8.363 -            SDL_SetError ("Error processing the FLAC file [LOST_SYNC].");
   8.364 +    case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
   8.365 +        SDL_SetError("Error processing the FLAC file [LOST_SYNC].");
   8.366          break;
   8.367 -        case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
   8.368 -            SDL_SetError ("Error processing the FLAC file [BAD_HEADER].");
   8.369 +    case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
   8.370 +        SDL_SetError("Error processing the FLAC file [BAD_HEADER].");
   8.371          break;
   8.372 -        case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
   8.373 -            SDL_SetError ("Error processing the FLAC file [CRC_MISMATCH].");
   8.374 +    case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
   8.375 +        SDL_SetError("Error processing the FLAC file [CRC_MISMATCH].");
   8.376          break;
   8.377 -        case FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM:
   8.378 -            SDL_SetError ("Error processing the FLAC file [UNPARSEABLE].");
   8.379 +    case FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM:
   8.380 +        SDL_SetError("Error processing the FLAC file [UNPARSEABLE].");
   8.381          break;
   8.382 -        default:
   8.383 -            SDL_SetError ("Error processing the FLAC file [UNKNOWN].");
   8.384 +    default:
   8.385 +        SDL_SetError("Error processing the FLAC file [UNKNOWN].");
   8.386          break;
   8.387      }
   8.388  }
   8.389 @@ -496,243 +478,130 @@
   8.390  /* Load an FLAC stream from an SDL_RWops object */
   8.391  static void *FLAC_CreateFromRW(SDL_RWops *src, int freesrc)
   8.392  {
   8.393 -    FLAC_music *music;
   8.394 +    FLAC_Music *music;
   8.395      int init_stage = 0;
   8.396      int was_error = 1;
   8.397  
   8.398 -    if (!Mix_Init(MIX_INIT_FLAC)) {
   8.399 +    music = (FLAC_Music *)SDL_calloc(1, sizeof(*music));
   8.400 +    if (!music) {
   8.401 +        SDL_OutOfMemory();
   8.402 +        return NULL;
   8.403 +    }
   8.404 +    music->src = src;
   8.405 +    music->volume = MIX_MAX_VOLUME;
   8.406 +
   8.407 +    music->flac_decoder = flac.FLAC__stream_decoder_new();
   8.408 +    if (music->flac_decoder) {
   8.409 +        init_stage++; /* stage 1! */
   8.410 +
   8.411 +        if (flac.FLAC__stream_decoder_init_stream(
   8.412 +                    music->flac_decoder,
   8.413 +                    flac_read_music_cb, flac_seek_music_cb,
   8.414 +                    flac_tell_music_cb, flac_length_music_cb,
   8.415 +                    flac_eof_music_cb, flac_write_music_cb,
   8.416 +                    flac_metadata_music_cb, flac_error_music_cb,
   8.417 +                    music) == FLAC__STREAM_DECODER_INIT_STATUS_OK) {
   8.418 +            init_stage++; /* stage 2! */
   8.419 +
   8.420 +            if (flac.FLAC__stream_decoder_process_until_end_of_metadata(music->flac_decoder)) {
   8.421 +                was_error = 0;
   8.422 +            } else {
   8.423 +                SDL_SetError("FLAC__stream_decoder_process_until_end_of_metadata() failed");
   8.424 +            }
   8.425 +        } else {
   8.426 +            SDL_SetError("FLAC__stream_decoder_init_stream() failed");
   8.427 +        }
   8.428 +    } else {
   8.429 +        SDL_SetError("FLAC__stream_decoder_new() failed");
   8.430 +    }
   8.431 +
   8.432 +    if (was_error) {
   8.433 +        switch (init_stage) {
   8.434 +            case 2:
   8.435 +                flac.FLAC__stream_decoder_finish(music->flac_decoder);
   8.436 +            case 1:
   8.437 +                flac.FLAC__stream_decoder_delete(music->flac_decoder);
   8.438 +            case 0:
   8.439 +                SDL_free(music);
   8.440 +                break;
   8.441 +        }
   8.442          return NULL;
   8.443      }
   8.444  
   8.445 -    music = (FLAC_music *)SDL_calloc(1, sizeof (*music));
   8.446 -    if (music) {
   8.447 -        /* Initialize the music structure */
   8.448 -        music->volume = MIX_MAX_VOLUME;
   8.449 -        music->section = -1;
   8.450 -        music->src = src;
   8.451 -        music->freesrc = freesrc;
   8.452 -        music->flac_data.max_to_read = 0;
   8.453 -        music->flac_data.overflow = NULL;
   8.454 -        music->flac_data.overflow_len = 0;
   8.455 -        music->flac_data.overflow_read = 0;
   8.456 -        music->flac_data.data = NULL;
   8.457 -        music->flac_data.data_len = 0;
   8.458 -        music->flac_data.data_read = 0;
   8.459 -
   8.460 -        init_stage++; // stage 1!
   8.461 -
   8.462 -        music->flac_decoder = flac.FLAC__stream_decoder_new ();
   8.463 -
   8.464 -        if (music->flac_decoder != NULL) {
   8.465 -            init_stage++; // stage 2!
   8.466 -
   8.467 -            if (flac.FLAC__stream_decoder_init_stream(
   8.468 -                        music->flac_decoder,
   8.469 -                        flac_read_music_cb, flac_seek_music_cb,
   8.470 -                        flac_tell_music_cb, flac_length_music_cb,
   8.471 -                        flac_eof_music_cb, flac_write_music_cb,
   8.472 -                        flac_metadata_music_cb, flac_error_music_cb,
   8.473 -                        music) == FLAC__STREAM_DECODER_INIT_STATUS_OK) {
   8.474 -                init_stage++; // stage 3!
   8.475 -
   8.476 -                if (flac.FLAC__stream_decoder_process_until_end_of_metadata
   8.477 -                                        (music->flac_decoder)) {
   8.478 -                    was_error = 0;
   8.479 -                } else {
   8.480 -                    SDL_SetError("FLAC__stream_decoder_process_until_end_of_metadata() failed");
   8.481 -                }
   8.482 -            } else {
   8.483 -                SDL_SetError("FLAC__stream_decoder_init_stream() failed");
   8.484 -            }
   8.485 -        } else {
   8.486 -            SDL_SetError("FLAC__stream_decoder_new() failed");
   8.487 -        }
   8.488 -
   8.489 -        if (was_error) {
   8.490 -            switch (init_stage) {
   8.491 -                case 3:
   8.492 -                    flac.FLAC__stream_decoder_finish(music->flac_decoder);
   8.493 -                case 2:
   8.494 -                    flac.FLAC__stream_decoder_delete(music->flac_decoder);
   8.495 -                case 1:
   8.496 -                case 0:
   8.497 -                    SDL_free(music);
   8.498 -                    break;
   8.499 -            }
   8.500 -            return NULL;
   8.501 -        }
   8.502 -    } else {
   8.503 -        SDL_OutOfMemory();
   8.504 -    }
   8.505 +    music->freesrc = freesrc;
   8.506      return music;
   8.507  }
   8.508  
   8.509  /* Set the volume for an FLAC stream */
   8.510  static void FLAC_SetVolume(void *context, int volume)
   8.511  {
   8.512 -    FLAC_music *music = (FLAC_music *)context;
   8.513 +    FLAC_Music *music = (FLAC_Music *)context;
   8.514      music->volume = volume;
   8.515  }
   8.516  
   8.517  /* Start playback of a given FLAC stream */
   8.518 -static int FLAC_Play(void *context)
   8.519 +static int FLAC_Play(void *context, int play_count)
   8.520  {
   8.521 -    FLAC_music *music = (FLAC_music *)context;
   8.522 -    music->playing = SDL_TRUE;
   8.523 -    return 0;
   8.524 -}
   8.525 -
   8.526 -/* Return non-zero if a stream is currently playing */
   8.527 -static SDL_bool FLAC_IsPlaying(void *context)
   8.528 -{
   8.529 -    FLAC_music *music = (FLAC_music *)context;
   8.530 -    return music->playing;
   8.531 +    FLAC_Music *music = (FLAC_Music *)context;
   8.532 +    music->play_count = play_count;
   8.533 +    return FLAC_Seek(music, 0.0);
   8.534  }
   8.535  
   8.536  /* Read some FLAC stream data and convert it for output */
   8.537 -static void FLAC_getsome(FLAC_music *music)
   8.538 +static int FLAC_GetSome(void *context, void *data, int bytes, SDL_bool *done)
   8.539  {
   8.540 -    SDL_AudioCVT *cvt;
   8.541 +    FLAC_Music *music = (FLAC_Music *)context;
   8.542 +    int filled;
   8.543  
   8.544 -    /* GET AUDIO WAVE DATA */
   8.545 -    // set the max number of characters to read
   8.546 -    music->flac_data.max_to_read = 8192;
   8.547 -    music->flac_data.data_len = music->flac_data.max_to_read;
   8.548 -    music->flac_data.data_read = 0;
   8.549 -    if (!music->flac_data.data) {
   8.550 -        music->flac_data.data = (char *)SDL_malloc (music->flac_data.data_len);
   8.551 +    filled = SDL_AudioStreamGet(music->stream, data, bytes);
   8.552 +    if (filled != 0) {
   8.553 +        return filled;
   8.554      }
   8.555  
   8.556 -    // we have data to read
   8.557 -    while(music->flac_data.max_to_read > 0) {
   8.558 -        // first check if there is data in the overflow from before
   8.559 -        if (music->flac_data.overflow) {
   8.560 -            size_t overflow_len = music->flac_data.overflow_read;
   8.561 +    if (!music->play_count) {
   8.562 +        /* All done */
   8.563 +        *done = SDL_TRUE;
   8.564 +        return 0;
   8.565 +    }
   8.566  
   8.567 -            if (overflow_len > (size_t)music->flac_data.max_to_read) {
   8.568 -                size_t overflow_extra_len = overflow_len -
   8.569 -                                                music->flac_data.max_to_read;
   8.570 +    if (!flac.FLAC__stream_decoder_process_single(music->flac_decoder)) {
   8.571 +        SDL_SetError("FLAC__stream_decoder_process_single() failed");
   8.572 +        return -1;
   8.573 +    }
   8.574  
   8.575 -                SDL_memcpy (music->flac_data.data+music->flac_data.data_read,
   8.576 -                    music->flac_data.overflow, music->flac_data.max_to_read);
   8.577 -                music->flac_data.data_read += music->flac_data.max_to_read;
   8.578 -                SDL_memcpy (music->flac_data.overflow,
   8.579 -                    music->flac_data.overflow + music->flac_data.max_to_read,
   8.580 -                    overflow_extra_len);
   8.581 -                music->flac_data.overflow_len = (int)overflow_extra_len;
   8.582 -                music->flac_data.overflow_read = (int)overflow_extra_len;
   8.583 -                music->flac_data.max_to_read = 0;
   8.584 -            } else {
   8.585 -                SDL_memcpy (music->flac_data.data+music->flac_data.data_read,
   8.586 -                    music->flac_data.overflow, overflow_len);
   8.587 -                music->flac_data.data_read += (int)overflow_len;
   8.588 -                SDL_free (music->flac_data.overflow);
   8.589 -                music->flac_data.overflow = NULL;
   8.590 -                music->flac_data.overflow_len = 0;
   8.591 -                music->flac_data.overflow_read = 0;
   8.592 -                music->flac_data.max_to_read -= (int)overflow_len;
   8.593 +    if (flac.FLAC__stream_decoder_get_state(music->flac_decoder) == FLAC__STREAM_DECODER_END_OF_STREAM) {
   8.594 +        if (music->play_count == 1) {
   8.595 +            music->play_count = 0;
   8.596 +            SDL_AudioStreamFlush(music->stream);
   8.597 +        } else {
   8.598 +            int play_count = -1;
   8.599 +            if (music->play_count > 0) {
   8.600 +                play_count = (music->play_count - 1);
   8.601              }
   8.602 -        } else {
   8.603 -            if (!flac.FLAC__stream_decoder_process_single (
   8.604 -                                                        music->flac_decoder)) {
   8.605 -                music->flac_data.max_to_read = 0;
   8.606 -            }
   8.607 -
   8.608 -            if (flac.FLAC__stream_decoder_get_state (music->flac_decoder)
   8.609 -                                    == FLAC__STREAM_DECODER_END_OF_STREAM) {
   8.610 -                music->flac_data.max_to_read = 0;
   8.611 +            if (FLAC_Play(music, play_count) < 0) {
   8.612 +                return -1;
   8.613              }
   8.614          }
   8.615      }
   8.616 -
   8.617 -    if (music->flac_data.data_read <= 0) {
   8.618 -        if (music->flac_data.data_read == 0) {
   8.619 -            music->playing = SDL_FALSE;
   8.620 -        }
   8.621 -        return;
   8.622 -    }
   8.623 -    cvt = &music->cvt;
   8.624 -    if (music->section < 0) {
   8.625 -        SDL_BuildAudioCVT (cvt, AUDIO_S16, (Uint8)music->flac_data.channels,
   8.626 -                        (int)music->flac_data.sample_rate,
   8.627 -                        music_spec.format,
   8.628 -                        music_spec.channels,
   8.629 -                        music_spec.freq);
   8.630 -        if (cvt->buf) {
   8.631 -            SDL_free (cvt->buf);
   8.632 -        }
   8.633 -        cvt->buf = (Uint8 *)SDL_malloc (music->flac_data.data_len * cvt->len_mult);
   8.634 -        music->section = 0;
   8.635 -    }
   8.636 -    if (cvt->buf) {
   8.637 -        SDL_memcpy (cvt->buf, music->flac_data.data, music->flac_data.data_read);
   8.638 -        if (cvt->needed) {
   8.639 -            cvt->len = music->flac_data.data_read;
   8.640 -            SDL_ConvertAudio (cvt);
   8.641 -        } else {
   8.642 -            cvt->len_cvt = music->flac_data.data_read;
   8.643 -        }
   8.644 -        music->len_available = music->cvt.len_cvt;
   8.645 -        music->snd_available = music->cvt.buf;
   8.646 -    } else {
   8.647 -        SDL_SetError ("Out of memory");
   8.648 -        music->playing = SDL_FALSE;
   8.649 -    }
   8.650 +    return 0;
   8.651  }
   8.652  
   8.653  /* Play some of a stream previously started with FLAC_play() */
   8.654  static int FLAC_GetAudio(void *context, void *data, int bytes)
   8.655  {
   8.656 -    FLAC_music *music = (FLAC_music *)context;
   8.657 -    Uint8 *snd = (Uint8 *)data;
   8.658 -    int len = bytes;
   8.659 -    int mixable;
   8.660 -
   8.661 -    while ((len > 0) && music->playing) {
   8.662 -        if (!music->len_available) {
   8.663 -            FLAC_getsome (music);
   8.664 -        }
   8.665 -        mixable = len;
   8.666 -        if (mixable > music->len_available) {
   8.667 -            mixable = music->len_available;
   8.668 -        }
   8.669 -        if (music->volume == MIX_MAX_VOLUME) {
   8.670 -            SDL_memcpy (snd, music->snd_available, mixable);
   8.671 -        } else {
   8.672 -            SDL_MixAudioFormat(snd, music->snd_available, music_spec.format, mixable, music->volume);
   8.673 -        }
   8.674 -        music->len_available -= mixable;
   8.675 -        music->snd_available += mixable;
   8.676 -        len -= mixable;
   8.677 -        snd += mixable;
   8.678 -    }
   8.679 -
   8.680 -    return len;
   8.681 +    FLAC_Music *music = (FLAC_Music *)context;
   8.682 +    return music_pcm_getaudio(context, data, bytes, music->volume, FLAC_GetSome);
   8.683  }
   8.684  
   8.685  /* Jump (seek) to a given position (position is in seconds) */
   8.686  static int FLAC_Seek(void *context, double position)
   8.687  {
   8.688 -    FLAC_music *music = (FLAC_music *)context;
   8.689 -    double seek_sample = music->flac_data.sample_rate * position;
   8.690 +    FLAC_Music *music = (FLAC_Music *)context;
   8.691 +    double seek_sample = music->sample_rate * position;
   8.692  
   8.693 -    // clear data if it has data
   8.694 -    if (music->flac_data.data) {
   8.695 -        SDL_free (music->flac_data.data);
   8.696 -        music->flac_data.data = NULL;
   8.697 -    }
   8.698 -
   8.699 -    // clear overflow if it has data
   8.700 -    if (music->flac_data.overflow) {
   8.701 -        SDL_free (music->flac_data.overflow);
   8.702 -        music->flac_data.overflow = NULL;
   8.703 -    }
   8.704 -
   8.705 -    if (!flac.FLAC__stream_decoder_seek_absolute (music->flac_decoder,
   8.706 -                                        (FLAC__uint64)seek_sample)) {
   8.707 -        if (flac.FLAC__stream_decoder_get_state (music->flac_decoder)
   8.708 -                                == FLAC__STREAM_DECODER_SEEK_ERROR) {
   8.709 -            flac.FLAC__stream_decoder_flush (music->flac_decoder);
   8.710 +    if (!flac.FLAC__stream_decoder_seek_absolute(music->flac_decoder, (FLAC__uint64)seek_sample)) {
   8.711 +        if (flac.FLAC__stream_decoder_get_state(music->flac_decoder) == FLAC__STREAM_DECODER_SEEK_ERROR) {
   8.712 +            flac.FLAC__stream_decoder_flush(music->flac_decoder);
   8.713          }
   8.714  
   8.715          SDL_SetError("Seeking of FLAC stream failed: libFLAC seek failed.");
   8.716 @@ -741,39 +610,22 @@
   8.717      return 0;
   8.718  }
   8.719  
   8.720 -/* Stop playback of a stream previously started with FLAC_play() */
   8.721 -static void FLAC_Stop(void *context)
   8.722 -{
   8.723 -    FLAC_music *music = (FLAC_music *)context;
   8.724 -    music->playing = SDL_FALSE;
   8.725 -}
   8.726 -
   8.727 -/* Close the given FLAC_music object */
   8.728 +/* Close the given FLAC_Music object */
   8.729  static void FLAC_Delete(void *context)
   8.730  {
   8.731 -    FLAC_music *music = (FLAC_music *)context;
   8.732 +    FLAC_Music *music = (FLAC_Music *)context;
   8.733      if (music) {
   8.734          if (music->flac_decoder) {
   8.735 -            flac.FLAC__stream_decoder_finish (music->flac_decoder);
   8.736 -            flac.FLAC__stream_decoder_delete (music->flac_decoder);
   8.737 +            flac.FLAC__stream_decoder_finish(music->flac_decoder);
   8.738 +            flac.FLAC__stream_decoder_delete(music->flac_decoder);
   8.739          }
   8.740 -
   8.741 -        if (music->flac_data.data) {
   8.742 -            SDL_free (music->flac_data.data);
   8.743 +        if (music->stream) {
   8.744 +            SDL_FreeAudioStream(music->stream);
   8.745          }
   8.746 -
   8.747 -        if (music->flac_data.overflow) {
   8.748 -            SDL_free (music->flac_data.overflow);
   8.749 -        }
   8.750 -
   8.751 -        if (music->cvt.buf) {
   8.752 -            SDL_free (music->cvt.buf);
   8.753 -        }
   8.754 -
   8.755          if (music->freesrc) {
   8.756              SDL_RWclose(music->src);
   8.757          }
   8.758 -        SDL_free (music);
   8.759 +        SDL_free(music);
   8.760      }
   8.761  }
   8.762  
   8.763 @@ -791,12 +643,12 @@
   8.764      NULL,   /* CreateFromFile */
   8.765      FLAC_SetVolume,
   8.766      FLAC_Play,
   8.767 -    FLAC_IsPlaying,
   8.768 +    NULL,   /* IsPlaying */
   8.769      FLAC_GetAudio,
   8.770      FLAC_Seek,
   8.771      NULL,   /* Pause */
   8.772      NULL,   /* Resume */
   8.773 -    FLAC_Stop,
   8.774 +    NULL,   /* Stop */
   8.775      FLAC_Delete,
   8.776      NULL,   /* Close */
   8.777      FLAC_Unload,
     9.1 --- a/music_fluidsynth.c	Fri Oct 20 21:55:03 2017 -0700
     9.2 +++ b/music_fluidsynth.c	Fri Oct 20 23:39:04 2017 -0700
     9.3 @@ -117,14 +117,13 @@
     9.4  
     9.5  
     9.6  typedef struct {
     9.7 -    SDL_AudioCVT convert;
     9.8      fluid_synth_t *synth;
     9.9 -    fluid_player_t* player;
    9.10 -} FluidSynthMidiSong;
    9.11 +    fluid_player_t *player;
    9.12 +    SDL_AudioStream *stream;
    9.13 +    void *buffer;
    9.14 +    int buffer_size;
    9.15 +} FLUIDSYNTH_Music;
    9.16  
    9.17 -static Uint16 format;
    9.18 -static Uint8 channels;
    9.19 -static int freq;
    9.20  
    9.21  static int fluidsynth_check_soundfont(const char *path, void *data)
    9.22  {
    9.23 @@ -151,165 +150,134 @@
    9.24      if (!Mix_EachSoundFont(fluidsynth_check_soundfont, NULL)) {
    9.25          return -1;
    9.26      }
    9.27 -
    9.28 -    format = spec->format;
    9.29 -    channels = spec->channels;
    9.30 -    freq = spec->freq;
    9.31 -
    9.32      return 0;
    9.33  }
    9.34  
    9.35 -static FluidSynthMidiSong *fluidsynth_loadsong_common(int (*function)(FluidSynthMidiSong*, void*), void *data)
    9.36 +static FLUIDSYNTH_Music *FLUIDSYNTH_LoadMusic(void *data)
    9.37  {
    9.38 -    FluidSynthMidiSong *song;
    9.39 -    fluid_settings_t *settings = NULL;
    9.40 +    SDL_RWops *src = (SDL_RWops *)data;
    9.41 +    FLUIDSYNTH_Music *music;
    9.42 +    fluid_settings_t *settings;
    9.43  
    9.44 -    if ((song = SDL_calloc(1, sizeof(FluidSynthMidiSong)))) {
    9.45 -        if (SDL_BuildAudioCVT(&song->convert, AUDIO_S16, 2, freq, format, channels, freq) >= 0) {
    9.46 -            if ((settings = fluidsynth.new_fluid_settings())) {
    9.47 -                fluidsynth.fluid_settings_setnum(settings, "synth.sample-rate", (double) freq);
    9.48 +    if ((music = SDL_calloc(1, sizeof(FLUIDSYNTH_Music)))) {
    9.49 +        int channels = 2;
    9.50 +        if ((music->stream = SDL_NewAudioStream(AUDIO_S16SYS, channels, music_spec.freq, music_spec.format, music_spec.channels, music_spec.freq))) {
    9.51 +            music->buffer_size = music_spec.samples * sizeof(Sint16) * channels;
    9.52 +            if ((music->buffer = SDL_malloc(music->buffer_size))) {
    9.53 +                if ((settings = fluidsynth.new_fluid_settings())) {
    9.54 +                    fluidsynth.fluid_settings_setnum(settings, "synth.sample-rate", (double) music_spec.freq);
    9.55  
    9.56 -                if ((song->synth = fluidsynth.new_fluid_synth(settings))) {
    9.57 -                    if (Mix_EachSoundFont(fluidsynth_load_soundfont, (void*) song->synth)) {
    9.58 -                        if ((song->player = fluidsynth.new_fluid_player(song->synth))) {
    9.59 -                            if (function(song, data)) return song;
    9.60 -                            fluidsynth.delete_fluid_player(song->player);
    9.61 -                        } else {
    9.62 -                            Mix_SetError("Failed to create FluidSynth player");
    9.63 +                    if ((music->synth = fluidsynth.new_fluid_synth(settings))) {
    9.64 +                        if (Mix_EachSoundFont(fluidsynth_load_soundfont, (void*) music->synth)) {
    9.65 +                            if ((music->player = fluidsynth.new_fluid_player(music->synth))) {
    9.66 +                                void *buffer;
    9.67 +                                size_t size;
    9.68 +
    9.69 +                                buffer = SDL_LoadFile_RW(src, &size, SDL_FALSE);
    9.70 +                                if (buffer) {
    9.71 +                                    if (fluidsynth.fluid_player_add_mem(music->player, buffer, size) == FLUID_OK) {
    9.72 +                                        SDL_free(buffer);
    9.73 +                                        return music;
    9.74 +                                    } else {
    9.75 +                                        Mix_SetError("FluidSynth failed to load in-memory song");
    9.76 +                                    }
    9.77 +                                    SDL_free(buffer);
    9.78 +                                } else {
    9.79 +                                    SDL_OutOfMemory();
    9.80 +                                }
    9.81 +                                fluidsynth.delete_fluid_player(music->player);
    9.82 +                            } else {
    9.83 +                                Mix_SetError("Failed to create FluidSynth player");
    9.84 +                            }
    9.85                          }
    9.86 +                        fluidsynth.delete_fluid_synth(music->synth);
    9.87 +                    } else {
    9.88 +                        Mix_SetError("Failed to create FluidSynth synthesizer");
    9.89                      }
    9.90 -                    fluidsynth.delete_fluid_synth(song->synth);
    9.91 +                    fluidsynth.delete_fluid_settings(settings);
    9.92                  } else {
    9.93 -                    Mix_SetError("Failed to create FluidSynth synthesizer");
    9.94 +                    Mix_SetError("Failed to create FluidSynth settings");
    9.95                  }
    9.96 -                fluidsynth.delete_fluid_settings(settings);
    9.97              } else {
    9.98 -                Mix_SetError("Failed to create FluidSynth settings");
    9.99 +                SDL_OutOfMemory();
   9.100              }
   9.101 -        } else {
   9.102 -            Mix_SetError("Failed to set up audio conversion");
   9.103          }
   9.104 -        SDL_free(song);
   9.105 +        SDL_free(music);
   9.106      } else {
   9.107 -        Mix_SetError("Insufficient memory for song");
   9.108 +        SDL_OutOfMemory();
   9.109      }
   9.110      return NULL;
   9.111  }
   9.112  
   9.113 -static int fluidsynth_loadsong_RW_internal(FluidSynthMidiSong *song, void *data)
   9.114 -{
   9.115 -    Sint64 offset;
   9.116 -    size_t size;
   9.117 -    char *buffer;
   9.118 -    SDL_RWops *src = (SDL_RWops*) data;
   9.119 -
   9.120 -    offset = SDL_RWtell(src);
   9.121 -    SDL_RWseek(src, 0, RW_SEEK_END);
   9.122 -    size = (size_t)(SDL_RWtell(src) - offset);
   9.123 -    SDL_RWseek(src, offset, RW_SEEK_SET);
   9.124 -
   9.125 -    if ((buffer = (char*) SDL_malloc(size))) {
   9.126 -        if(SDL_RWread(src, buffer, size, 1) == 1) {
   9.127 -            if (fluidsynth.fluid_player_add_mem(song->player, buffer, size) == FLUID_OK) {
   9.128 -                SDL_free(buffer);
   9.129 -                return 1;
   9.130 -            } else {
   9.131 -                Mix_SetError("FluidSynth failed to load in-memory song");
   9.132 -            }
   9.133 -        } else {
   9.134 -            Mix_SetError("Failed to read in-memory song");
   9.135 -        }
   9.136 -        SDL_free(buffer);
   9.137 -    } else {
   9.138 -        Mix_SetError("Insufficient memory for song");
   9.139 -    }
   9.140 -    return 0;
   9.141 -}
   9.142 -
   9.143  static void *FLUIDSYNTH_CreateFromRW(SDL_RWops *src, int freesrc)
   9.144  {
   9.145 -    FluidSynthMidiSong *song;
   9.146 +    FLUIDSYNTH_Music *music;
   9.147  
   9.148 -    song = fluidsynth_loadsong_common(fluidsynth_loadsong_RW_internal, (void*) src);
   9.149 -    if (song && freesrc) {
   9.150 +    music = FLUIDSYNTH_LoadMusic(src);
   9.151 +    if (music && freesrc) {
   9.152          SDL_RWclose(src);
   9.153      }
   9.154 -    return song;
   9.155 +    return music;
   9.156  }
   9.157  
   9.158  static void FLUIDSYNTH_SetVolume(void *context, int volume)
   9.159  {
   9.160 -    FluidSynthMidiSong *song = (FluidSynthMidiSong *)context;
   9.161 +    FLUIDSYNTH_Music *music = (FLUIDSYNTH_Music *)context;
   9.162      /* FluidSynth's default is 0.2. Make 1.2 the maximum. */
   9.163 -    fluidsynth.fluid_synth_set_gain(song->synth, (float) (volume * 1.2 / MIX_MAX_VOLUME));
   9.164 +    fluidsynth.fluid_synth_set_gain(music->synth, (float) (volume * 1.2 / MIX_MAX_VOLUME));
   9.165  }
   9.166  
   9.167 -static int FLUIDSYNTH_Play(void *context)
   9.168 +static int FLUIDSYNTH_Play(void *context, int play_count)
   9.169  {
   9.170 -    FluidSynthMidiSong *song = (FluidSynthMidiSong *)context;
   9.171 -    fluidsynth.fluid_player_set_loop(song->player, 1);
   9.172 -    fluidsynth.fluid_player_play(song->player);
   9.173 +    FLUIDSYNTH_Music *music = (FLUIDSYNTH_Music *)context;
   9.174 +    fluidsynth.fluid_player_set_loop(music->player, play_count);
   9.175 +    fluidsynth.fluid_player_play(music->player);
   9.176      return 0;
   9.177  }
   9.178  
   9.179  static SDL_bool FLUIDSYNTH_IsPlaying(void *context)
   9.180  {
   9.181 -    FluidSynthMidiSong *song = (FluidSynthMidiSong *)context;
   9.182 -    return fluidsynth.fluid_player_get_status(song->player) == FLUID_PLAYER_PLAYING ? SDL_TRUE : SDL_FALSE;
   9.183 +    FLUIDSYNTH_Music *music = (FLUIDSYNTH_Music *)context;
   9.184 +    return fluidsynth.fluid_player_get_status(music->player) == FLUID_PLAYER_PLAYING ? SDL_TRUE : SDL_FALSE;
   9.185  }
   9.186  
   9.187 +static int FLUIDSYNTH_GetSome(void *context, void *data, int bytes, SDL_bool *done)
   9.188 +{
   9.189 +    int filled;
   9.190 +
   9.191 +    filled = SDL_AudioStreamGet(music->stream, data, bytes);
   9.192 +    if (filled != 0) {
   9.193 +        return filled;
   9.194 +    }
   9.195 +
   9.196 +    /* FIXME: What happens at end of song? */
   9.197 +    if (fluidsynth.fluid_synth_write_s16(music->synth, mixer_spec.samples, music->buffer, 0, 2, music->buffer, 1, 2) != FLUID_OK) {
   9.198 +        Mix_SetError("Error generating FluidSynth audio");
   9.199 +        return -1;
   9.200 +    }
   9.201 +    if (SDL_AudioStreamPut(music->stream, music->buffer, music->buffer_size) < 0) {
   9.202 +        return -1;
   9.203 +    }
   9.204 +    return 0;
   9.205 +}
   9.206  static int FLUIDSYNTH_GetAudio(void *context, void *data, int bytes)
   9.207  {
   9.208 -    int result = -1;
   9.209 -    int frames = bytes / channels / ((format & 0xFF) / 8);
   9.210 -    int src_len = frames * 4; /* 16-bit stereo */
   9.211 -    void *src = dest;
   9.212 -
   9.213 -    if (bytes < src_len) {
   9.214 -        if (!(src = SDL_malloc(src_len))) {
   9.215 -            Mix_SetError("Insufficient memory for audio conversion");
   9.216 -            return result;
   9.217 -        }
   9.218 -    }
   9.219 -
   9.220 -    if (fluidsynth.fluid_synth_write_s16(song->synth, frames, src, 0, 2, src, 1, 2) != FLUID_OK) {
   9.221 -        Mix_SetError("Error generating FluidSynth audio");
   9.222 -        goto finish;
   9.223 -    }
   9.224 -
   9.225 -    song->convert.buf = src;
   9.226 -    song->convert.len = src_len;
   9.227 -
   9.228 -    if (SDL_ConvertAudio(&song->convert) < 0) {
   9.229 -        Mix_SetError("Error during audio conversion");
   9.230 -        goto finish;
   9.231 -    }
   9.232 -
   9.233 -    if (src != dest)
   9.234 -        SDL_memcpy(dest, src, bytes);
   9.235 -
   9.236 -    result = 0;
   9.237 -
   9.238 -finish:
   9.239 -    if (src != dest)
   9.240 -        SDL_free(src);
   9.241 -
   9.242 -    return result;
   9.243 +    return music_pcm_getaudio(context, data, bytes, MIX_MAX_VOLUME, FLUIDSYNTH_GetSome);
   9.244  }
   9.245  
   9.246  static void FLUIDSYNTH_Stop(void *context)
   9.247  {
   9.248 -    FluidSynthMidiSong *song = (FluidSynthMidiSong *)context;
   9.249 -    fluidsynth.fluid_player_stop(song->player);
   9.250 +    FLUIDSYNTH_Music *music = (FLUIDSYNTH_Music *)context;
   9.251 +    fluidsynth.fluid_player_stop(music->player);
   9.252  }
   9.253  
   9.254  static void FLUIDSYNTH_Delete(void *context)
   9.255  {
   9.256 -    FluidSynthMidiSong *song = (FluidSynthMidiSong *)context;
   9.257 -    fluidsynth.delete_fluid_player(song->player);
   9.258 -    fluidsynth.delete_fluid_settings(fluidsynth.fluid_synth_get_settings(song->synth));
   9.259 -    fluidsynth.delete_fluid_synth(song->synth);
   9.260 -    SDL_free(song);
   9.261 +    FLUIDSYNTH_Music *music = (FLUIDSYNTH_Music *)context;
   9.262 +    fluidsynth.delete_fluid_player(music->player);
   9.263 +    fluidsynth.delete_fluid_settings(fluidsynth.fluid_synth_get_settings(music->synth));
   9.264 +    fluidsynth.delete_fluid_synth(music->synth);
   9.265 +    SDL_free(music);
   9.266  }
   9.267  
   9.268  Mix_MusicInterface Mix_MusicInterface_FLUIDSYNTH =
    10.1 --- a/music_mad.c	Fri Oct 20 21:55:03 2017 -0700
    10.2 +++ b/music_mad.c	Fri Oct 20 23:39:04 2017 -0700
    10.3 @@ -25,84 +25,176 @@
    10.4  
    10.5  #include "mad.h"
    10.6  
    10.7 +
    10.8 +/* NOTE: The dithering functions are GPL, which should be fine if your
    10.9 +         application is GPL (which would need to be true if you enabled
   10.10 +         libmad support in SDL_mixer). If you're using libmad under the
   10.11 +         commercial license, you need to disable this code.
   10.12 +*/
   10.13 +/************************ dithering functions ***************************/
   10.14 +
   10.15 +#ifdef MUSIC_MP3_MAD_GPL_DITHERING
   10.16 +
   10.17 +/* All dithering done here is taken from the GPL'ed xmms-mad plugin. */
   10.18 +
   10.19 +/* Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura.       */
   10.20 +/* Any feedback is very welcome. For any question, comments,       */
   10.21 +/* see http://www.math.keio.ac.jp/matumoto/emt.html or email       */
   10.22 +/* matumoto@math.keio.ac.jp                                        */
   10.23 +
   10.24 +/* Period parameters */
   10.25 +#define MP3_DITH_N 624
   10.26 +#define MP3_DITH_M 397
   10.27 +#define MATRIX_A 0x9908b0df   /* constant vector a */
   10.28 +#define UPPER_MASK 0x80000000 /* most significant w-r bits */
   10.29 +#define LOWER_MASK 0x7fffffff /* least significant r bits */
   10.30 +
   10.31 +/* Tempering parameters */
   10.32 +#define TEMPERING_MASK_B 0x9d2c5680
   10.33 +#define TEMPERING_MASK_C 0xefc60000
   10.34 +#define TEMPERING_SHIFT_U(y)  (y >> 11)
   10.35 +#define TEMPERING_SHIFT_S(y)  (y << 7)
   10.36 +#define TEMPERING_SHIFT_T(y)  (y << 15)
   10.37 +#define TEMPERING_SHIFT_L(y)  (y >> 18)
   10.38 +
   10.39 +static unsigned long mt[MP3_DITH_N]; /* the array for the state vector  */
   10.40 +static int mti=MP3_DITH_N+1; /* mti==MP3_DITH_N+1 means mt[MP3_DITH_N] is not initialized */
   10.41 +
   10.42 +/* initializing the array with a NONZERO seed */
   10.43 +static void sgenrand(unsigned long seed)
   10.44 +{
   10.45 +    /* setting initial seeds to mt[MP3_DITH_N] using         */
   10.46 +    /* the generator Line 25 of Table 1 in          */
   10.47 +    /* [KNUTH 1981, The Art of Computer Programming */
   10.48 +    /*    Vol. 2 (2nd Ed.), pp102]                  */
   10.49 +    mt[0]= seed & 0xffffffff;
   10.50 +    for (mti=1; mti<MP3_DITH_N; mti++)
   10.51 +        mt[mti] = (69069 * mt[mti-1]) & 0xffffffff;
   10.52 +}
   10.53 +
   10.54 +static unsigned long genrand(void)
   10.55 +{
   10.56 +    unsigned long y;
   10.57 +    static unsigned long mag01[2]={0x0, MATRIX_A};
   10.58 +    /* mag01[x] = x * MATRIX_A  for x=0,1 */
   10.59 +
   10.60 +    if (mti >= MP3_DITH_N) { /* generate MP3_DITH_N words at one time */
   10.61 +        int kk;
   10.62 +
   10.63 +        if (mti == MP3_DITH_N+1)   /* if sgenrand() has not been called, */
   10.64 +            sgenrand(4357); /* a default initial seed is used   */
   10.65 +
   10.66 +        for (kk=0;kk<MP3_DITH_N-MP3_DITH_M;kk++) {
   10.67 +            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
   10.68 +            mt[kk] = mt[kk+MP3_DITH_M] ^ (y >> 1) ^ mag01[y & 0x1];
   10.69 +        }
   10.70 +        for (;kk<MP3_DITH_N-1;kk++) {
   10.71 +            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
   10.72 +            mt[kk] = mt[kk+(MP3_DITH_M-MP3_DITH_N)] ^ (y >> 1) ^ mag01[y & 0x1];
   10.73 +        }
   10.74 +        y = (mt[MP3_DITH_N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
   10.75 +        mt[MP3_DITH_N-1] = mt[MP3_DITH_M-1] ^ (y >> 1) ^ mag01[y & 0x1];
   10.76 +
   10.77 +        mti = 0;
   10.78 +    }
   10.79 +
   10.80 +    y = mt[mti++];
   10.81 +    y ^= TEMPERING_SHIFT_U(y);
   10.82 +    y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
   10.83 +    y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
   10.84 +    y ^= TEMPERING_SHIFT_L(y);
   10.85 +
   10.86 +    return y;
   10.87 +}
   10.88 +
   10.89 +static long triangular_dither_noise(int nbits) {
   10.90 +    /* parameter nbits : the peak-to-peak amplitude desired (in bits)
   10.91 +     *  use with nbits set to    2 + nber of bits to be trimmed.
   10.92 +     * (because triangular is made from two uniformly distributed processes,
   10.93 +     * it starts at 2 bits peak-to-peak amplitude)
   10.94 +     * see The Theory of Dithered Quantization by Robert Alexander Wannamaker
   10.95 +     * for complete proof of why that's optimal
   10.96 +     */
   10.97 +    long v = (genrand()/2 - genrand()/2); /* in ]-2^31, 2^31[ */
   10.98 +    long P = 1 << (32 - nbits); /* the power of 2 */
   10.99 +    v /= P;
  10.100 +    /* now v in ]-2^(nbits-1), 2^(nbits-1) [ */
  10.101 +
  10.102 +    return v;
  10.103 +}
  10.104 +
  10.105 +#endif /* MUSIC_MP3_MAD_GPL_DITHERING */
  10.106 +
  10.107 +
  10.108  #define MAD_INPUT_BUFFER_SIZE   (5*8192)
  10.109 -#define MAD_OUTPUT_BUFFER_SIZE  8192
  10.110  
  10.111  enum {
  10.112      MS_input_eof      = 0x0001,
  10.113      MS_input_error    = 0x0001,
  10.114 -    MS_decode_eof     = 0x0002,
  10.115 -    MS_decode_error   = 0x0004,
  10.116 +    MS_decode_error   = 0x0002,
  10.117      MS_error_flags    = 0x000f,
  10.118 -
  10.119 -    MS_playing        = 0x0100,
  10.120 -    MS_cvt_decoded    = 0x0200,
  10.121  };
  10.122  
  10.123  typedef struct {
  10.124 +    int play_count;
  10.125      SDL_RWops *src;
  10.126      int freesrc;
  10.127      struct mad_stream stream;
  10.128      struct mad_frame frame;
  10.129      struct mad_synth synth;
  10.130 -    int frames_read;
  10.131      mad_timer_t next_frame_start;
  10.132      int volume;
  10.133      int status;
  10.134 -    int output_begin, output_end;
  10.135 -    SDL_AudioSpec mixer;
  10.136 -    SDL_AudioCVT cvt;
  10.137 +    SDL_AudioStream *audiostream;
  10.138  
  10.139      unsigned char input_buffer[MAD_INPUT_BUFFER_SIZE + MAD_BUFFER_GUARD];
  10.140 -    unsigned char *output_buffer;
  10.141 -} mad_data;
  10.142 +} MAD_Music;
  10.143  
  10.144  
  10.145 +static int MAD_Seek(void *context, double position);
  10.146 +
  10.147  static void *MAD_CreateFromRW(SDL_RWops *src, int freesrc)
  10.148  {
  10.149 -    mad_data *mp3_mad;
  10.150 +    MAD_Music *music;
  10.151  
  10.152 -    mp3_mad = (mad_data *)SDL_calloc(1, sizeof(mad_data));
  10.153 -    if (mp3_mad) {
  10.154 -        mp3_mad->src = src;
  10.155 -        mp3_mad->freesrc = freesrc;
  10.156 -        mad_stream_init(&mp3_mad->stream);
  10.157 -        mad_frame_init(&mp3_mad->frame);
  10.158 -        mad_synth_init(&mp3_mad->synth);
  10.159 -        mad_timer_reset(&mp3_mad->next_frame_start);
  10.160 -        mp3_mad->volume = MIX_MAX_VOLUME;
  10.161 -        mp3_mad->mixer = music_spec;
  10.162 +    music = (MAD_Music *)SDL_calloc(1, sizeof(MAD_Music));
  10.163 +    if (!music) {
  10.164 +        SDL_OutOfMemory();
  10.165 +        return NULL;
  10.166      }
  10.167 -    return mp3_mad;
  10.168 +    music->src = src;
  10.169 +    music->volume = MIX_MAX_VOLUME;
  10.170 +
  10.171 +    mad_stream_init(&music->stream);
  10.172 +    mad_frame_init(&music->frame);
  10.173 +    mad_synth_init(&music->synth);
  10.174 +    mad_timer_reset(&music->next_frame_start);
  10.175 +
  10.176 +    music->freesrc = freesrc;
  10.177 +    return music;
  10.178  }
  10.179  
  10.180  static void MAD_SetVolume(void *context, int volume)
  10.181  {
  10.182 -    mad_data *mp3_mad = (mad_data *)context;
  10.183 -    mp3_mad->volume = volume;
  10.184 +    MAD_Music *music = (MAD_Music *)context;
  10.185 +    music->volume = volume;
  10.186  }
  10.187  
  10.188  /* Starts the playback. */
  10.189 -static int MAD_Play(void *context)
  10.190 +static int MAD_Play(void *context, int play_count)
  10.191  {
  10.192 -    mad_data *mp3_mad = (mad_data *)context;
  10.193 -    mp3_mad->status |= MS_playing;
  10.194 -    return 0;
  10.195 +    MAD_Music *music = (MAD_Music *)context;
  10.196 +    music->play_count = play_count;
  10.197 +    return MAD_Seek(music, 0.0);
  10.198  }
  10.199  
  10.200 -/* Returns true if the playing is engaged, false otherwise. */
  10.201 -static SDL_bool MAD_IsPlaying(void *context)
  10.202 +/* Reads the next frame from the file.
  10.203 +   Returns true on success or false on failure.
  10.204 + */
  10.205 +static SDL_bool read_next_frame(MAD_Music *music)
  10.206  {
  10.207 -    mad_data *mp3_mad = (mad_data *)context;
  10.208 -    return ((mp3_mad->status & MS_playing) != 0);
  10.209 -}
  10.210 -
  10.211 -/* Reads the next frame from the file.    Returns true on success or
  10.212 -   false on failure. */
  10.213 -static int
  10.214 -read_next_frame(mad_data *mp3_mad) {
  10.215 -    if (mp3_mad->stream.buffer == NULL ||
  10.216 -            mp3_mad->stream.error == MAD_ERROR_BUFLEN) {
  10.217 +    if (music->stream.buffer == NULL ||
  10.218 +        music->stream.error == MAD_ERROR_BUFLEN) {
  10.219          size_t read_size;
  10.220          size_t remaining;
  10.221          unsigned char *read_start;
  10.222 @@ -110,25 +202,25 @@
  10.223          /* There might be some bytes in the buffer left over from last
  10.224             time.    If so, move them down and read more bytes following
  10.225             them. */
  10.226 -        if (mp3_mad->stream.next_frame != NULL) {
  10.227 -            remaining = mp3_mad->stream.bufend - mp3_mad->stream.next_frame;
  10.228 -            memmove(mp3_mad->input_buffer, mp3_mad->stream.next_frame, remaining);
  10.229 -            read_start = mp3_mad->input_buffer + remaining;
  10.230 +        if (music->stream.next_frame != NULL) {
  10.231 +            remaining = music->stream.bufend - music->stream.next_frame;
  10.232 +            memmove(music->input_buffer, music->stream.next_frame, remaining);
  10.233 +            read_start = music->input_buffer + remaining;
  10.234              read_size = MAD_INPUT_BUFFER_SIZE - remaining;
  10.235  
  10.236          } else {
  10.237              read_size = MAD_INPUT_BUFFER_SIZE;
  10.238 -            read_start = mp3_mad->input_buffer;
  10.239 +            read_start = music->input_buffer;
  10.240              remaining = 0;
  10.241          }
  10.242  
  10.243          /* Now read additional bytes from the input file. */
  10.244 -        read_size = SDL_RWread(mp3_mad->src, read_start, 1, read_size);
  10.245 +        read_size = SDL_RWread(music->src, read_start, 1, read_size);
  10.246  
  10.247          if (read_size == 0) {
  10.248 -            if ((mp3_mad->status & (MS_input_eof | MS_input_error)) == 0) {
  10.249 +            if ((music->status & (MS_input_eof | MS_input_error)) == 0) {
  10.250                  /* FIXME: how to detect error? */
  10.251 -                mp3_mad->status |= MS_input_eof;
  10.252 +                music->status |= MS_input_eof;
  10.253  
  10.254                  /* At the end of the file, we must stuff MAD_BUFFER_GUARD
  10.255                     number of 0 bytes. */
  10.256 @@ -138,37 +230,43 @@
  10.257          }
  10.258  
  10.259          /* Now feed those bytes into the libmad stream. */
  10.260 -        mad_stream_buffer(&mp3_mad->stream, mp3_mad->input_buffer,
  10.261 +        mad_stream_buffer(&music->stream, music->input_buffer,
  10.262                                              read_size + remaining);
  10.263 -        mp3_mad->stream.error = MAD_ERROR_NONE;
  10.264 +        music->stream.error = MAD_ERROR_NONE;
  10.265      }
  10.266  
  10.267      /* Now ask libmad to extract a frame from the data we just put in
  10.268         its buffer. */
  10.269 -    if (mad_frame_decode(&mp3_mad->frame, &mp3_mad->stream)) {
  10.270 -        if (MAD_RECOVERABLE(mp3_mad->stream.error)) {
  10.271 -            return 0;
  10.272 +    if (mad_frame_decode(&music->frame, &music->stream)) {
  10.273 +        if (MAD_RECOVERABLE(music->stream.error)) {
  10.274 +            return SDL_FALSE;
  10.275  
  10.276 -        } else if (mp3_mad->stream.error == MAD_ERROR_BUFLEN) {
  10.277 -            return 0;
  10.278 +        } else if (music->stream.error == MAD_ERROR_BUFLEN) {
  10.279 +            return SDL_FALSE;
  10.280  
  10.281          } else {
  10.282 -            mp3_mad->status |= MS_decode_error;
  10.283 -            return 0;
  10.284 +            Mix_SetError("mad_frame_decode() failed, corrupt stream?");
  10.285 +            music->status |= MS_decode_error;
  10.286 +            return SDL_FALSE;
  10.287          }
  10.288      }
  10.289  
  10.290 -    mp3_mad->frames_read++;
  10.291 -    mad_timer_add(&mp3_mad->next_frame_start, mp3_mad->frame.header.duration);
  10.292 +    mad_timer_add(&music->next_frame_start, music->frame.header.duration);
  10.293  
  10.294 -    return 1;
  10.295 +    return SDL_TRUE;
  10.296  }
  10.297  
  10.298  /* Scale a MAD sample to 16 bits for output. */
  10.299 -static signed int
  10.300 -scale(mad_fixed_t sample) {
  10.301 +static Sint16 scale(mad_fixed_t sample)
  10.302 +{
  10.303 +    const int n_bits_to_loose = MAD_F_FRACBITS + 1 - 16;
  10.304 +
  10.305      /* round */
  10.306 -    sample += (1L << (MAD_F_FRACBITS - 16));
  10.307 +    sample += (1L << (n_bits_to_loose - 1));
  10.308 +
  10.309 +#ifdef MUSIC_MP3_MAD_GPL_DITHERING
  10.310 +    sample += triangular_dither_noise(n_bits_to_loose + 1);
  10.311 +#endif
  10.312  
  10.313      /* clip */
  10.314      if (sample >= MAD_F_ONE)
  10.315 @@ -177,161 +275,132 @@
  10.316          sample = -MAD_F_ONE;
  10.317  
  10.318      /* quantize */
  10.319 -    return sample >> (MAD_F_FRACBITS + 1 - 16);
  10.320 +    return (Sint16)(sample >> n_bits_to_loose);
  10.321  }
  10.322  
  10.323  /* Once the frame has been read, copies its samples into the output buffer. */
  10.324 -static void
  10.325 -decode_frame(mad_data *mp3_mad) {
  10.326 +static SDL_bool decode_frame(MAD_Music *music)
  10.327 +{
  10.328      struct mad_pcm *pcm;
  10.329 -    unsigned int nchannels, nsamples;
  10.330 +    unsigned int i, nchannels, nsamples;
  10.331      mad_fixed_t const *left_ch, *right_ch;
  10.332 -    unsigned char *out;
  10.333 -    int ret;
  10.334 +    Sint16 *buffer, *dst;
  10.335 +    int result;
  10.336  
  10.337 -    mad_synth_frame(&mp3_mad->synth, &mp3_mad->frame);
  10.338 -    pcm = &mp3_mad->synth.pcm;
  10.339 +    mad_synth_frame(&music->synth, &music->frame);
  10.340 +    pcm = &music->synth.pcm;
  10.341  
  10.342 -    if ((mp3_mad->status & MS_cvt_decoded) == 0) {
  10.343 -        mp3_mad->status |= MS_cvt_decoded;
  10.344 -
  10.345 -        /* The first frame determines some key properties of the stream.
  10.346 -           In particular, it tells us enough to set up the convert
  10.347 -           structure now. */
  10.348 -        SDL_BuildAudioCVT(&mp3_mad->cvt, AUDIO_S16, pcm->channels, mp3_mad->frame.header.samplerate, mp3_mad->mixer.format, mp3_mad->mixer.channels, mp3_mad->mixer.freq);
  10.349 -    }
  10.350 -
  10.351 -    if (!mp3_mad->output_buffer) {
  10.352 -        size_t sz = MAD_OUTPUT_BUFFER_SIZE;
  10.353 -        if (mp3_mad->cvt.len_mult > 1) {
  10.354 -                sz *= mp3_mad->cvt.len_mult;
  10.355 -        }
  10.356 -        mp3_mad->output_buffer = (unsigned char *) SDL_malloc(sz);
  10.357 -    }
  10.358 -    out = mp3_mad->output_buffer + mp3_mad->output_end;
  10.359 -
  10.360 -    /* pcm->samplerate contains the sampling frequency */
  10.361 -
  10.362 -    nchannels = pcm->channels;
  10.363 -    nsamples    = pcm->length;
  10.364 -    left_ch     = pcm->samples[0];
  10.365 -    right_ch    = pcm->samples[1];
  10.366 -
  10.367 -    while (nsamples--) {
  10.368 -        signed int sample;
  10.369 -
  10.370 -        /* output sample(s) in 16-bit signed little-endian PCM */
  10.371 -
  10.372 -        sample = scale(*left_ch++);
  10.373 -        *out++ = ((sample >> 0) & 0xff);
  10.374 -        *out++ = ((sample >> 8) & 0xff);
  10.375 -
  10.376 -        if (nchannels == 2) {
  10.377 -            sample = scale(*right_ch++);
  10.378 -            *out++ = ((sample >> 0) & 0xff);
  10.379 -            *out++ = ((sample >> 8) & 0xff);
  10.380 +    if (!music->audiostream) {
  10.381 +        music->audiostream = SDL_NewAudioStream(AUDIO_S16, pcm->channels, pcm->samplerate, music_spec.format, music_spec.channels, music_spec.freq);
  10.382 +        if (!music->audiostream) {
  10.383 +            return SDL_FALSE;
  10.384          }
  10.385      }
  10.386  
  10.387 -    mp3_mad->output_end = out - mp3_mad->output_buffer;
  10.388 -    /*assert(mp3_mad->output_end <= MAD_OUTPUT_BUFFER_SIZE);*/
  10.389 +    nchannels = pcm->channels;
  10.390 +    nsamples = pcm->length;
  10.391 +    left_ch = pcm->samples[0];
  10.392 +    right_ch = pcm->samples[1];
  10.393 +    buffer = SDL_stack_alloc(Sint16, nsamples*nchannels);
  10.394 +    if (!buffer) {
  10.395 +        SDL_OutOfMemory();
  10.396 +        return SDL_FALSE;
  10.397 +    }
  10.398 +
  10.399 +    dst = buffer;
  10.400 +    if (nchannels == 1) {
  10.401 +        for (i = nsamples; i--;) {
  10.402 +            *dst++ = scale(*left_ch++);
  10.403 +        }
  10.404 +    } else {
  10.405 +        for (i = nsamples; i--;) {
  10.406 +            *dst++ = scale(*left_ch++);
  10.407 +            *dst++ = scale(*right_ch++);
  10.408 +        }
  10.409 +    }
  10.410 +
  10.411 +    result = SDL_AudioStreamPut(music->audiostream, buffer, (nsamples * nchannels * sizeof(Sint16)));
  10.412 +    SDL_stack_free(buffer);
  10.413 +
  10.414 +    if (result < 0) {
  10.415 +        return SDL_FALSE;
  10.416 +    }
  10.417 +    return SDL_TRUE;
  10.418  }
  10.419  
  10.420 -static int MAD_GetAudio(void *context, void *data, int bytes)
  10.421 +static int MAD_GetSome(void *context, void *data, int bytes, SDL_bool *done)
  10.422  {
  10.423 -    mad_data *mp3_mad = (mad_data *)context;
  10.424 -    Uint8 *stream = (Uint8 *)data;
  10.425 -    int len = bytes;
  10.426 -    int bytes_remaining;
  10.427 -    int num_bytes;
  10.428 -    Uint8 *out;
  10.429 +    MAD_Music *music = (MAD_Music *)context;
  10.430 +    int filled;
  10.431  
  10.432 -    if ((mp3_mad->status & MS_playing) == 0) {
  10.433 -        /* We're not supposed to be playing, so send silence instead. */
  10.434 -        SDL_memset(stream, 0, len);
  10.435 +    if (music->audiostream) {
  10.436 +        filled = SDL_AudioStreamGet(music->audiostream, data, bytes);
  10.437 +        if (filled != 0) {
  10.438 +            return filled;
  10.439 +        }
  10.440 +    }
  10.441 +
  10.442 +    if (!music->play_count) {
  10.443 +        /* All done */
  10.444 +        *done = SDL_TRUE;
  10.445          return 0;
  10.446      }
  10.447  
  10.448 -    out = stream;
  10.449 -    bytes_remaining = len;
  10.450 -    while (bytes_remaining > 0) {
  10.451 -        if (mp3_mad->output_end == mp3_mad->output_begin) {
  10.452 -            /* We need to get a new frame. */
  10.453 -            mp3_mad->output_begin = 0;
  10.454 -            mp3_mad->output_end = 0;
  10.455 -            if (!read_next_frame(mp3_mad)) {
  10.456 -                if ((mp3_mad->status & MS_error_flags) != 0) {
  10.457 -                    /* Couldn't read a frame; either an error condition or
  10.458 -                       end-of-file.    Stop. */
  10.459 -                    SDL_memset(out, 0, bytes_remaining);
  10.460 -                    mp3_mad->status &= ~MS_playing;
  10.461 -                    return bytes_remaining;
  10.462 -                }
  10.463 -            } else {
  10.464 -                decode_frame(mp3_mad);
  10.465 +    if (read_next_frame(music)) {
  10.466 +        if (!decode_frame(music)) {
  10.467 +            return -1;
  10.468 +        }
  10.469 +    } else {
  10.470 +        int play_count = -1;
  10.471  
  10.472 -                /* Now convert the frame data to the appropriate format for
  10.473 -                   output. */
  10.474 -                mp3_mad->cvt.buf = mp3_mad->output_buffer;
  10.475 -                mp3_mad->cvt.len = mp3_mad->output_end;
  10.476 -
  10.477 -                mp3_mad->output_end = (int)(mp3_mad->output_end * mp3_mad->cvt.len_ratio);
  10.478 -                /*assert(mp3_mad->output_end <= MAD_OUTPUT_BUFFER_SIZE);*/
  10.479 -                SDL_ConvertAudio(&mp3_mad->cvt);
  10.480 -            }
  10.481 +        if (music->status & MS_decode_error) {
  10.482 +            return -1;
  10.483          }
  10.484  
  10.485 -        num_bytes = mp3_mad->output_end - mp3_mad->output_begin;
  10.486 -        if (bytes_remaining < num_bytes) {
  10.487 -            num_bytes = bytes_remaining;
  10.488 +        if (music->play_count > 0) {
  10.489 +            play_count = (music->play_count - 1);
  10.490          }
  10.491 -
  10.492 -        if (mp3_mad->volume == MIX_MAX_VOLUME) {
  10.493 -            SDL_memcpy(out, mp3_mad->output_buffer + mp3_mad->output_begin, num_bytes);
  10.494 -        } else {
  10.495 -            SDL_MixAudioFormat(out, mp3_mad->output_buffer + mp3_mad->output_begin,
  10.496 -                               mp3_mad->mixer.format, num_bytes, mp3_mad->volume);
  10.497 +        if (MAD_Play(music, play_count) < 0) {
  10.498 +            return -1;
  10.499          }
  10.500 -        out += num_bytes;
  10.501 -        mp3_mad->output_begin += num_bytes;
  10.502 -        bytes_remaining -= num_bytes;
  10.503      }
  10.504      return 0;
  10.505  }
  10.506 +static int MAD_GetAudio(void *context, void *data, int bytes)
  10.507 +{
  10.508 +    MAD_Music *music = (MAD_Music *)context;
  10.509 +    return music_pcm_getaudio(context, data, bytes, music->volume, MAD_GetSome);
  10.510 +}
  10.511  
  10.512  static int MAD_Seek(void *context, double position)
  10.513  {
  10.514 -    mad_data *mp3_mad = (mad_data *)context;
  10.515 +    MAD_Music *music = (MAD_Music *)context;
  10.516      mad_timer_t target;
  10.517      int int_part;
  10.518  
  10.519      int_part = (int)position;
  10.520      mad_timer_set(&target, int_part, (int)((position - int_part) * 1000000), 1000000);
  10.521  
  10.522 -    if (mad_timer_compare(mp3_mad->next_frame_start, target) > 0) {
  10.523 +    if (mad_timer_compare(music->next_frame_start, target) > 0) {
  10.524          /* In order to seek backwards in a VBR file, we have to rewind and
  10.525             start again from the beginning.    This isn't necessary if the
  10.526             file happens to be CBR, of course; in that case we could seek
  10.527             directly to the frame we want.    But I leave that little
  10.528             optimization for the future developer who discovers she really
  10.529             needs it. */
  10.530 -        mp3_mad->frames_read = 0;
  10.531 -        mad_timer_reset(&mp3_mad->next_frame_start);
  10.532 -        mp3_mad->status &= ~MS_error_flags;
  10.533 -        mp3_mad->output_begin = 0;
  10.534 -        mp3_mad->output_end = 0;
  10.535 +        mad_timer_reset(&music->next_frame_start);
  10.536 +        music->status &= ~MS_error_flags;
  10.537  
  10.538 -        SDL_RWseek(mp3_mad->src, 0, RW_SEEK_SET);
  10.539 +        SDL_RWseek(music->src, 0, RW_SEEK_SET);
  10.540      }
  10.541  
  10.542      /* Now we have to skip frames until we come to the right one.
  10.543         Again, only truly necessary if the file is VBR. */
  10.544 -    while (mad_timer_compare(mp3_mad->next_frame_start, target) < 0) {
  10.545 -        if (!read_next_frame(mp3_mad)) {
  10.546 -            if ((mp3_mad->status & MS_error_flags) != 0) {
  10.547 +    while (mad_timer_compare(music->next_frame_start, target) < 0) {
  10.548 +        if (!read_next_frame(music)) {
  10.549 +            if ((music->status & MS_error_flags) != 0) {
  10.550                  /* Couldn't read a frame; either an error condition or
  10.551                       end-of-file.    Stop. */
  10.552 -                mp3_mad->status &= ~MS_playing;
  10.553                  return Mix_SetError("Seek position out of range");
  10.554              }
  10.555          }
  10.556 @@ -344,25 +413,21 @@
  10.557      return 0;
  10.558  }
  10.559  
  10.560 -/* Stops the playback. */
  10.561 -static void MAD_Stop(void *context)
  10.562 -{
  10.563 -    mad_data *mp3_mad = (mad_data *)context;
  10.564 -    mp3_mad->status &= ~MS_playing;
  10.565 -}
  10.566 -
  10.567  static void MAD_Delete(void *context)
  10.568  {
  10.569 -    mad_data *mp3_mad = (mad_data *)context;
  10.570 -    mad_stream_finish(&mp3_mad->stream);
  10.571 -    mad_frame_finish(&mp3_mad->frame);
  10.572 -    mad_synth_finish(&mp3_mad->synth);
  10.573 +    MAD_Music *music = (MAD_Music *)context;
  10.574  
  10.575 -    if (mp3_mad->freesrc) {
  10.576 -        SDL_RWclose(mp3_mad->src);
  10.577 +    mad_stream_finish(&music->stream);
  10.578 +    mad_frame_finish(&music->frame);
  10.579 +    mad_synth_finish(&music->synth);
  10.580 +
  10.581 +    if (music->audiostream) {
  10.582 +        SDL_FreeAudioStream(music->audiostream);
  10.583      }
  10.584 -    SDL_free(mp3_mad->output_buffer);
  10.585 -    SDL_free(mp3_mad);
  10.586 +    if (music->freesrc) {
  10.587 +        SDL_RWclose(music->src);
  10.588 +    }
  10.589 +    SDL_free(music);
  10.590  }
  10.591  
  10.592  Mix_MusicInterface Mix_MusicInterface_MAD =
  10.593 @@ -373,21 +438,21 @@
  10.594      SDL_FALSE,
  10.595      SDL_FALSE,
  10.596  
  10.597 -    NULL,     /* Load */
  10.598 -    NULL,     /* Open */
  10.599 +    NULL,   /* Load */
  10.600 +    NULL,   /* Open */
  10.601      MAD_CreateFromRW,
  10.602 -    NULL,     /* CreateFromFile */
  10.603 +    NULL,   /* CreateFromFile */
  10.604      MAD_SetVolume,
  10.605      MAD_Play,
  10.606 -    MAD_IsPlaying,
  10.607 +    NULL,   /* IsPlaying */
  10.608      MAD_GetAudio,
  10.609      MAD_Seek,
  10.610 -    NULL,     /* Pause */
  10.611 -    NULL,     /* Resume */
  10.612 -    MAD_Stop,
  10.613 +    NULL,   /* Pause */
  10.614 +    NULL,   /* Resume */
  10.615 +    NULL,   /* Stop */
  10.616      MAD_Delete,
  10.617 -    NULL,     /* Close */
  10.618 -    NULL,     /* Unload */
  10.619 +    NULL,   /* Close */
  10.620 +    NULL,   /* Unload */
  10.621  };
  10.622  
  10.623  #endif /* MUSIC_MP3_MAD */
    11.1 --- a/music_mikmod.c	Fri Oct 20 21:55:03 2017 -0700
    11.2 +++ b/music_mikmod.c	Fri Oct 20 23:39:04 2017 -0700
    11.3 @@ -20,6 +20,7 @@
    11.4  */
    11.5  
    11.6  #ifdef MUSIC_MOD_MIKMOD
    11.7 +#error Implement play_count and audio stream conversion
    11.8  
    11.9  /* This file supports MOD tracker music streams */
   11.10  
    12.1 --- a/music_modplug.c	Fri Oct 20 21:55:03 2017 -0700
    12.2 +++ b/music_modplug.c	Fri Oct 20 23:39:04 2017 -0700
    12.3 @@ -49,12 +49,8 @@
    12.4  };
    12.5  
    12.6  
    12.7 -static int current_output_channels = 0;
    12.8 -static int music_swap8 = 0;
    12.9 -static int music_swap16 = 0;
   12.10  static ModPlug_Settings settings;
   12.11  
   12.12 -
   12.13  #ifdef MODPLUG_DYNAMIC
   12.14  
   12.15  static int MODPLUG_Load(void)
   12.16 @@ -149,58 +145,49 @@
   12.17  
   12.18  #endif /* MODPLUG_DYNAMIC */
   12.19  
   12.20 +typedef struct
   12.21 +{
   12.22 +    int play_count;
   12.23 +    ModPlugFile *file;
   12.24 +    SDL_AudioStream *stream;
   12.25 +    void *buffer;
   12.26 +    int buffer_size;
   12.27 +} MODPLUG_Music;
   12.28 +
   12.29 +
   12.30 +static int MODPLUG_Seek(void *context, double position);
   12.31 +static void MODPLUG_Delete(void *context);
   12.32 +
   12.33  static int MODPLUG_Open(const SDL_AudioSpec *spec)
   12.34  {
   12.35 +    /* ModPlug supports U8 or S16 audio output */
   12.36      modplug.ModPlug_GetSettings(&settings);
   12.37 -    settings.mFlags=MODPLUG_ENABLE_OVERSAMPLING;
   12.38 -    current_output_channels=spec->channels;
   12.39 -    settings.mChannels=spec->channels>1?2:1;
   12.40 -    settings.mBits=spec->format&0xFF;
   12.41 -
   12.42 -    music_swap8 = 0;
   12.43 -    music_swap16 = 0;
   12.44 -
   12.45 -    switch(spec->format)
   12.46 -    {
   12.47 -        case AUDIO_U8:
   12.48 -        case AUDIO_S8: {
   12.49 -            if (spec->format == AUDIO_S8) {
   12.50 -                music_swap8 = 1;
   12.51 -            }
   12.52 -            settings.mBits=8;
   12.53 -        }
   12.54 -        break;
   12.55 -
   12.56 -        case AUDIO_S16LSB:
   12.57 -        case AUDIO_S16MSB: {
   12.58 -            /* See if we need to correct MikMod mixing */
   12.59 -#if SDL_BYTEORDER == SDL_LIL_ENDIAN
   12.60 -            if (spec->format == AUDIO_S16MSB) {
   12.61 -#else
   12.62 -            if (spec->format == AUDIO_S16LSB) {
   12.63 -#endif
   12.64 -                music_swap16 = 1;
   12.65 -            }
   12.66 -            settings.mBits=16;
   12.67 -        }
   12.68 -        break;
   12.69 -
   12.70 -        default: {
   12.71 -            Mix_SetError("Unknown hardware audio format");
   12.72 -            return -1;
   12.73 -        }
   12.74 -
   12.75 +    settings.mFlags = MODPLUG_ENABLE_OVERSAMPLING;
   12.76 +    if (spec->channels == 1) {
   12.77 +        settings.mChannels = 1;
   12.78 +    } else {
   12.79 +        settings.mChannels = 2;
   12.80      }
   12.81 -
   12.82 -    settings.mFrequency=spec->freq; /*TODO: limit to 11025, 22050, or 44100 ? */
   12.83 -    settings.mResamplingMode=MODPLUG_RESAMPLE_FIR;
   12.84 -    settings.mReverbDepth=0;
   12.85 -    settings.mReverbDelay=100;
   12.86 -    settings.mBassAmount=0;
   12.87 -    settings.mBassRange=50;
   12.88 -    settings.mSurroundDepth=0;
   12.89 -    settings.mSurroundDelay=10;
   12.90 -    settings.mLoopCount=0;
   12.91 +    if (SDL_AUDIO_BITSIZE(spec->format) == 8) {
   12.92 +        settings.mBits = 8;
   12.93 +    } else {
   12.94 +        settings.mBits = 16;
   12.95 +    }
   12.96 +    if (spec->freq >= 44100) {
   12.97 +        settings.mFrequency = 44100;
   12.98 +    } else if (spec->freq >= 22050) {
   12.99 +        settings.mFrequency = 22050;
  12.100 +    } else {
  12.101 +        settings.mFrequency = 11025;
  12.102 +    }
  12.103 +    settings.mResamplingMode = MODPLUG_RESAMPLE_FIR;
  12.104 +    settings.mReverbDepth = 0;
  12.105 +    settings.mReverbDelay = 100;
  12.106 +    settings.mBassAmount = 0;
  12.107 +    settings.mBassRange = 50;
  12.108 +    settings.mSurroundDepth = 0;
  12.109 +    settings.mSurroundDelay = 10;
  12.110 +    settings.mLoopCount = 0;
  12.111      modplug.ModPlug_SetSettings(&settings);
  12.112      return 0;
  12.113  }
  12.114 @@ -208,25 +195,45 @@
  12.115  /* Load a modplug stream from an SDL_RWops object */
  12.116  void *MODPLUG_CreateFromRW(SDL_RWops *src, int freesrc)
  12.117  {
  12.118 -    ModPlugFile *music = NULL;
  12.119 -    Sint64 offset;
  12.120 -    size_t sz;
  12.121 -    char *buf;
  12.122 +    MODPLUG_Music *music;
  12.123 +    void *buffer;
  12.124 +    size_t size;
  12.125  
  12.126 -    offset = SDL_RWtell(src);
  12.127 -    SDL_RWseek(src, 0, RW_SEEK_END);
  12.128 -    sz = (size_t)(SDL_RWtell(src) - offset);
  12.129 -    SDL_RWseek(src, offset, RW_SEEK_SET);
  12.130 -    buf = (char*)SDL_malloc(sz);
  12.131 -    if (buf) {
  12.132 -        if (SDL_RWread(src, buf, sz, 1) == 1) {
  12.133 -            music = modplug.ModPlug_Load(buf, (int)sz);
  12.134 +    music = (MODPLUG_Music *)SDL_calloc(1, sizeof(*music));
  12.135 +    if (!music) {
  12.136 +        SDL_OutOfMemory();
  12.137 +        return NULL;
  12.138 +    }
  12.139 +
  12.140 +    music->stream = SDL_NewAudioStream((settings.mBits == 8) ? AUDIO_U8 : AUDIO_S16SYS, settings.mChannels, settings.mFrequency,
  12.141 +                                       music_spec.format, music_spec.channels, music_spec.freq);
  12.142 +    if (!music->stream) {
  12.143 +        MODPLUG_Delete(music);
  12.144 +        return NULL;
  12.145 +    }
  12.146 +
  12.147 +    music->buffer_size = music_spec.samples * (settings.mBits / 8) * settings.mChannels;
  12.148 +    music->buffer = SDL_malloc(music->buffer_size);
  12.149 +    if (!music->buffer) {
  12.150 +        MODPLUG_Delete(music);
  12.151 +        return NULL;
  12.152 +    }
  12.153 +
  12.154 +    buffer = SDL_LoadFile_RW(src, &size, SDL_FALSE);
  12.155 +    if (buffer) {
  12.156 +        music->file = modplug.ModPlug_Load(buffer, (int)size);
  12.157 +        if (!music->file) {
  12.158 +            Mix_SetError("ModPlug_Load failed");
  12.159          }
  12.160 -        SDL_free(buf);
  12.161 -    } else {
  12.162 -        SDL_OutOfMemory();
  12.163 +        SDL_free(buffer);
  12.164      }
  12.165 -    if (music && freesrc) {
  12.166 +
  12.167 +    if (!music->file) {
  12.168 +        MODPLUG_Delete(music);
  12.169 +        return NULL;
  12.170 +    }
  12.171 +
  12.172 +    if (freesrc) {
  12.173          SDL_RWclose(src);
  12.174      }
  12.175      return music;
  12.176 @@ -235,117 +242,83 @@
  12.177  /* Set the volume for a modplug stream */
  12.178  static void MODPLUG_SetVolume(void *context, int volume)
  12.179  {
  12.180 -    ModPlugFile *music = (ModPlugFile *)context;
  12.181 -    modplug.ModPlug_SetMasterVolume(music, volume*4);
  12.182 +    MODPLUG_Music *music = (MODPLUG_Music *)context;
  12.183 +    modplug.ModPlug_SetMasterVolume(music->file, volume*4);
  12.184  }
  12.185  
  12.186  /* Start playback of a given modplug stream */
  12.187 -static int MODPLUG_Play(void *context)
  12.188 +static int MODPLUG_Play(void *context, int play_count)
  12.189  {
  12.190 -    ModPlugFile *music = (ModPlugFile *)context;
  12.191 -    modplug.ModPlug_Seek(music,0);
  12.192 -    return 0;
  12.193 +    MODPLUG_Music *music = (MODPLUG_Music *)context;
  12.194 +    music->play_count = play_count;
  12.195 +    return MODPLUG_Seek(music, 0.0);
  12.196  }
  12.197  
  12.198  /* Play some of a stream previously started with modplug_play() */
  12.199 +static int MODPLUG_GetSome(void *context, void *data, int bytes, SDL_bool *done)
  12.200 +{
  12.201 +    MODPLUG_Music *music = (MODPLUG_Music *)context;
  12.202 +    int filled, amount;
  12.203 +
  12.204 +    filled = SDL_AudioStreamGet(music->stream, data, bytes);
  12.205 +    if (filled != 0) {
  12.206 +        return filled;
  12.207 +    }
  12.208 +
  12.209 +    if (!music->play_count) {
  12.210 +        /* All done */
  12.211 +        *done = SDL_TRUE;
  12.212 +        return 0;
  12.213 +    }
  12.214 +
  12.215 +    amount = modplug.ModPlug_Read(music->file, music->buffer, music->buffer_size);
  12.216 +    if (amount > 0) {
  12.217 +        if (SDL_AudioStreamPut(music->stream, music->buffer, amount) < 0) {
  12.218 +            return -1;
  12.219 +        }
  12.220 +    } else {
  12.221 +        if (music->play_count == 1) {
  12.222 +            music->play_count = 0;
  12.223 +            SDL_AudioStreamFlush(music->stream);
  12.224 +        } else {
  12.225 +            int play_count = -1;
  12.226 +            if (music->play_count > 0) {
  12.227 +                play_count = (music->play_count - 1);
  12.228 +            }
  12.229 +            if (MODPLUG_Play(music, play_count) < 0) {
  12.230 +                return -1;
  12.231 +            }
  12.232 +        }
  12.233 +    }
  12.234 +    return 0;
  12.235 +}
  12.236  static int MODPLUG_GetAudio(void *context, void *data, int bytes)
  12.237  {
  12.238 -    ModPlugFile *music = (ModPlugFile *)context;
  12.239 -    Uint8 *stream = (Uint8 *)data;
  12.240 -    int len = bytes;
  12.241 -    int consumed;
  12.242 -
  12.243 -    if (current_output_channels > 2) {
  12.244 -        int small_len = 2 * len / current_output_channels;
  12.245 -        int i;
  12.246 -        Uint8 *src, *dst;
  12.247 -
  12.248 -        i=modplug.ModPlug_Read(music, stream, small_len);
  12.249 -        consumed = (i / 2) * current_output_channels;
  12.250 -        if(i<small_len)
  12.251 -        {
  12.252 -            SDL_memset(stream+i,0,small_len-i);
  12.253 -        }
  12.254 -        /* and extend to len by copying channels */
  12.255 -        src = stream + small_len;
  12.256 -        dst = stream + len;
  12.257 -
  12.258 -        switch (settings.mBits) {
  12.259 -            case 8:
  12.260 -                for (i=small_len/2; i; --i) {
  12.261 -                    src -= 2;
  12.262 -                    dst -= current_output_channels;
  12.263 -                    dst[0] = src[0];
  12.264 -                    dst[1] = src[1];
  12.265 -                    dst[2] = src[0];
  12.266 -                    dst[3] = src[1];
  12.267 -                    if (current_output_channels == 6) {
  12.268 -                        dst[4] = src[0];
  12.269 -                        dst[5] = src[1];
  12.270 -                    }
  12.271 -                }
  12.272 -                break;
  12.273 -            case 16:
  12.274 -                for (i=small_len/4; i; --i) {
  12.275 -                    src -= 4;
  12.276 -                    dst -= 2 * current_output_channels;
  12.277 -                    dst[0] = src[0];
  12.278 -                    dst[1] = src[1];
  12.279 -                    dst[2] = src[2];
  12.280 -                    dst[3] = src[3];
  12.281 -                    dst[4] = src[0];
  12.282 -                    dst[5] = src[1];
  12.283 -                    dst[6] = src[2];
  12.284 -                    dst[7] = src[3];
  12.285 -                    if (current_output_channels == 6) {
  12.286 -                        dst[8] = src[0];
  12.287 -                        dst[9] = src[1];
  12.288 -                        dst[10] = src[2];
  12.289 -                        dst[11] = src[3];
  12.290 -                    }
  12.291 -                }
  12.292 -                break;
  12.293 -        }
  12.294 -    } else {
  12.295 -        consumed=modplug.ModPlug_Read(music, stream, len);
  12.296 -    }
  12.297 -    if (music_swap8) {
  12.298 -        Uint8 *dst;
  12.299 -        int i;
  12.300 -
  12.301 -        dst = stream;
  12.302 -        for (i=len; i; --i) {
  12.303 -            *dst++ ^= 0x80;
  12.304 -        }
  12.305 -    } else
  12.306 -    if (music_swap16) {
  12.307 -        Uint8 *dst, tmp;
  12.308 -        int i;
  12.309 -
  12.310 -        dst = stream;
  12.311 -        for (i=(len/2); i; --i) {
  12.312 -            tmp = dst[0];
  12.313 -            dst[0] = dst[1];
  12.314 -            dst[1] = tmp;
  12.315 -            dst += 2;
  12.316 -        }
  12.317 -    }
  12.318 -    return (len-consumed);
  12.319 +    return music_pcm_getaudio(context, data, bytes, MIX_MAX_VOLUME, MODPLUG_GetSome);
  12.320  }
  12.321  
  12.322  /* Jump (seek) to a given position */
  12.323  static int MODPLUG_Seek(void *context, double position)
  12.324  {
  12.325 -    ModPlugFile *music = (ModPlugFile *)context;
  12.326 -    modplug.ModPlug_Seek(music,(int)(position*1000));
  12.327 +    MODPLUG_Music *music = (MODPLUG_Music *)context;
  12.328 +    modplug.ModPlug_Seek(music->file, (int)(position*1000));
  12.329      return 0;
  12.330  }
  12.331  
  12.332  /* Close the given modplug stream */
  12.333  static void MODPLUG_Delete(void *context)
  12.334  {
  12.335 -    ModPlugFile *music = (ModPlugFile *)context;
  12.336 -    modplug.ModPlug_Unload(music);
  12.337 +    MODPLUG_Music *music = (MODPLUG_Music *)context;
  12.338 +    if (music->file) {
  12.339 +        modplug.ModPlug_Unload(music->file);
  12.340 +    }
  12.341 +    if (music->stream) {
  12.342 +        SDL_FreeAudioStream(music->stream);
  12.343 +    }
  12.344 +    if (music->buffer) {
  12.345 +        SDL_free(music->buffer);
  12.346 +    }
  12.347 +    SDL_free(music);
  12.348  }
  12.349  
  12.350  Mix_MusicInterface Mix_MusicInterface_MODPLUG =
    13.1 --- a/music_mpg123.c	Fri Oct 20 21:55:03 2017 -0700
    13.2 +++ b/music_mpg123.c	Fri Oct 20 23:39:04 2017 -0700
    13.3 @@ -25,6 +25,7 @@
    13.4  
    13.5  #include <stdio.h>      // For SEEK_SET
    13.6  
    13.7 +#include "SDL_assert.h"
    13.8  #include "SDL_loadso.h"
    13.9  
   13.10  #include "music_mpg123.h"
   13.11 @@ -46,6 +47,7 @@
   13.12      mpg123_handle *(*mpg123_new)(const char* decoder, int *error);
   13.13      int (*mpg123_open_handle)(mpg123_handle *mh, void *iohandle);
   13.14      const char* (*mpg123_plain_strerror)(int errcode);
   13.15 +    void (*mpg123_rates)(const long **list, size_t *number);
   13.16      int (*mpg123_read)(mpg123_handle *mh, unsigned char *outmemory, size_t outmemsize, size_t *done );
   13.17      int (*mpg123_replace_reader_handle)( mpg123_handle *mh, ssize_t (*r_read) (void *, void *, size_t), off_t (*r_lseek)(void *, off_t, int), void (*cleanup)(void*) );
   13.18      off_t (*mpg123_seek)( mpg123_handle *mh, off_t sampleoff, int whence );
   13.19 @@ -93,6 +95,7 @@
   13.20          FUNCTION_LOADER(mpg123_new, mpg123_handle *(*)(const char* decoder, int *error))
   13.21          FUNCTION_LOADER(mpg123_open_handle, int (*)(mpg123_handle *mh, void *iohandle))
   13.22          FUNCTION_LOADER(mpg123_plain_strerror, const char* (*)(int errcode))
   13.23 +        FUNCTION_LOADER(mpg123_rates, void (*)(const long **list, size_t *number));
   13.24          FUNCTION_LOADER(mpg123_read, int (*)(mpg123_handle *mh, unsigned char *outmemory, size_t outmemsize, size_t *done ))
   13.25          FUNCTION_LOADER(mpg123_replace_reader_handle, int (*)( mpg123_handle *mh, ssize_t (*r_read) (void *, void *, size_t), off_t (*r_lseek)(void *, off_t, int), void (*cleanup)(void*) ))
   13.26          FUNCTION_LOADER(mpg123_seek, off_t (*)( mpg123_handle *mh, off_t sampleoff, int whence ))
   13.27 @@ -119,58 +122,37 @@
   13.28  
   13.29  typedef struct
   13.30  {
   13.31 +    int play_count;
   13.32      SDL_RWops* src;
   13.33      int freesrc;
   13.34 -
   13.35 -    SDL_AudioSpec mixer;
   13.36 -
   13.37 -    SDL_bool playing;
   13.38      int volume;
   13.39  
   13.40      mpg123_handle* handle;
   13.41 +    SDL_AudioStream *stream;
   13.42 +    unsigned char *buffer;
   13.43 +    size_t buffer_size;
   13.44 +} MPG123_Music;
   13.45  
   13.46 -    int gotformat;
   13.47 -    SDL_AudioCVT cvt;
   13.48 -    Uint8 buf[8192];
   13.49 -    size_t len_available;
   13.50 -    Uint8* snd_available;
   13.51 -} mpg_data;
   13.52  
   13.53 -static
   13.54 -int
   13.55 -snd_format_to_mpg123(uint16_t sdl_fmt)
   13.56 -{
   13.57 -    switch (sdl_fmt)
   13.58 -    {
   13.59 -        case AUDIO_U8:     return MPG123_ENC_UNSIGNED_8;
   13.60 -        case AUDIO_U16SYS: return MPG123_ENC_UNSIGNED_16;
   13.61 -        case AUDIO_S8:     return MPG123_ENC_SIGNED_8;
   13.62 -        case AUDIO_S16SYS: return MPG123_ENC_SIGNED_16;
   13.63 -        case AUDIO_S32SYS: return MPG123_ENC_SIGNED_32;
   13.64 -    }
   13.65 +static int MPG123_Seek(void *context, double secs);
   13.66 +static void MPG123_Delete(void *context);
   13.67  
   13.68 -    return -1;
   13.69 -}
   13.70 -
   13.71 -static
   13.72 -Uint16
   13.73 -mpg123_format_to_sdl(int fmt)
   13.74 +static int mpg123_format_to_sdl(int fmt)
   13.75  {
   13.76      switch (fmt)
   13.77      {
   13.78 -        case MPG123_ENC_UNSIGNED_8:  return AUDIO_U8;
   13.79 -        case MPG123_ENC_UNSIGNED_16: return AUDIO_U16SYS;
   13.80 -        case MPG123_ENC_SIGNED_8:    return AUDIO_S8;
   13.81 -        case MPG123_ENC_SIGNED_16:   return AUDIO_S16SYS;
   13.82 -        case MPG123_ENC_SIGNED_32:   return AUDIO_S32SYS;
   13.83 +        case MPG123_ENC_SIGNED_8:       return AUDIO_S8;
   13.84 +        case MPG123_ENC_UNSIGNED_8:     return AUDIO_U8;
   13.85 +        case MPG123_ENC_SIGNED_16:      return AUDIO_S16SYS;
   13.86 +        case MPG123_ENC_UNSIGNED_16:    return AUDIO_U16SYS;
   13.87 +        case MPG123_ENC_SIGNED_32:      return AUDIO_S32SYS;
   13.88 +        case MPG123_ENC_FLOAT_32:       return AUDIO_F32SYS;
   13.89 +        default:                        return -1;
   13.90      }
   13.91 -
   13.92 -    return -1;
   13.93  }
   13.94  
   13.95 -static
   13.96 -char const*
   13.97 -mpg123_format_str(int fmt)
   13.98 +/*
   13.99 +static const char *mpg123_format_str(int fmt)
  13.100  {
  13.101      switch (fmt)
  13.102      {
  13.103 @@ -180,46 +162,42 @@
  13.104          f(MPG123_ENC_SIGNED_8)
  13.105          f(MPG123_ENC_SIGNED_16)
  13.106          f(MPG123_ENC_SIGNED_32)
  13.107 +        f(MPG123_ENC_FLOAT_32)
  13.108  #undef f
  13.109      }
  13.110 -
  13.111      return "unknown";
  13.112  }
  13.113 +*/
  13.114  
  13.115 -static
  13.116 -char const*
  13.117 -mpg_err(mpg123_handle* mpg, int code)
  13.118 +static char const* mpg_err(mpg123_handle* mpg, int result)
  13.119  {
  13.120      char const* err = "unknown error";
  13.121  
  13.122 -    if (mpg && code == MPG123_ERR) {
  13.123 +    if (mpg && result == MPG123_ERR) {
  13.124          err = mpg123.mpg123_strerror(mpg);
  13.125      } else {
  13.126 -        err = mpg123.mpg123_plain_strerror(code);
  13.127 +        err = mpg123.mpg123_plain_strerror(result);
  13.128      }
  13.129 -
  13.130      return err;
  13.131  }
  13.132  
  13.133  /* we're gonna override mpg123's I/O with these wrappers for RWops */
  13.134 -static
  13.135 -ssize_t rwops_read(void* p, void* dst, size_t n) {
  13.136 +static ssize_t rwops_read(void* p, void* dst, size_t n)
  13.137 +{
  13.138      return (ssize_t)SDL_RWread((SDL_RWops*)p, dst, 1, n);
  13.139  }
  13.140  
  13.141 -static
  13.142 -off_t rwops_seek(void* p, off_t offset, int whence) {
  13.143 +static off_t rwops_seek(void* p, off_t offset, int whence)
  13.144 +{
  13.145      return (off_t)SDL_RWseek((SDL_RWops*)p, (Sint64)offset, whence);
  13.146  }
  13.147  
  13.148 -static
  13.149 -void rwops_cleanup(void* p) {
  13.150 +static void rwops_cleanup(void* p)
  13.151 +{
  13.152      (void)p;
  13.153      /* do nothing, we will free the file later */
  13.154  }
  13.155  
  13.156 -static int getsome(mpg_data* m);
  13.157 -
  13.158  
  13.159  static int MPG123_Open(const SDL_AudioSpec *spec)
  13.160  {
  13.161 @@ -232,280 +210,191 @@
  13.162  
  13.163  static void *MPG123_CreateFromRW(SDL_RWops *src, int freesrc)
  13.164  {
  13.165 -    mpg_data* m;
  13.166 +    MPG123_Music *music;
  13.167      int result;
  13.168 -    int fmt;
  13.169 +    const long *rates;
  13.170 +    size_t i, num_rates;
  13.171  
  13.172 -    m = (mpg_data*)SDL_calloc(1, sizeof(mpg_data));
  13.173 -    if (!m) {
  13.174 +    music = (MPG123_Music*)SDL_calloc(1, sizeof(*music));
  13.175 +    if (!music) {
  13.176 +        return NULL;
  13.177 +    }
  13.178 +    music->src = src;
  13.179 +    music->volume = MIX_MAX_VOLUME;
  13.180 +
  13.181 +    /* Just assume 16-bit 2 channel audio for now */
  13.182 +    music->buffer_size = music_spec.samples * sizeof(Sint16) * 2;
  13.183 +    music->buffer = (unsigned char *)SDL_malloc(music->buffer_size);
  13.184 +    if (!music->buffer) {
  13.185 +        MPG123_Delete(music);
  13.186 +        SDL_OutOfMemory();
  13.187 +        return NULL;
  13.188 +    }
  13.189 +
  13.190 +    music->handle = mpg123.mpg123_new(0, &result);
  13.191 +    if (result != MPG123_OK) {
  13.192 +        MPG123_Delete(music);
  13.193 +        Mix_SetError("mpg123_new failed");
  13.194 +        return NULL;
  13.195 +    }
  13.196 +
  13.197 +    result = mpg123.mpg123_replace_reader_handle(
  13.198 +        music->handle,
  13.199 +        rwops_read, rwops_seek, rwops_cleanup
  13.200 +    );
  13.201 +    if (result != MPG123_OK) {
  13.202 +        MPG123_Delete(music);
  13.203 +        Mix_SetError("mpg123_replace_reader_handle: %s", mpg_err(music->handle, result));
  13.204 +        return NULL;
  13.205 +    }
  13.206 +
  13.207 +    result = mpg123.mpg123_format_none(music->handle);
  13.208 +    if (result != MPG123_OK) {
  13.209 +        MPG123_Delete(music);
  13.210 +        Mix_SetError("mpg123_format_none: %s", mpg_err(music->handle, result));
  13.211 +        return NULL;
  13.212 +    }
  13.213 +
  13.214 +    mpg123.mpg123_rates(&rates, &num_rates);
  13.215 +    for (i = 0; i < num_rates; ++i) {
  13.216 +        const int channels = (MPG123_MONO|MPG123_STEREO);
  13.217 +        const int formats = (MPG123_ENC_SIGNED_8 |
  13.218 +                             MPG123_ENC_UNSIGNED_8 |
  13.219 +                             MPG123_ENC_SIGNED_16 |
  13.220 +                             MPG123_ENC_UNSIGNED_16 |
  13.221 +                             MPG123_ENC_SIGNED_32 |
  13.222 +                             MPG123_ENC_FLOAT_32);
  13.223 +
  13.224 +        mpg123.mpg123_format(music->handle, rates[i], channels, formats);
  13.225 +    }
  13.226 +
  13.227 +    result = mpg123.mpg123_open_handle(music->handle, music->src);
  13.228 +    if (result != MPG123_OK) {
  13.229 +        MPG123_Delete(music);
  13.230 +        Mix_SetError("mpg123_open_handle: %s", mpg_err(music->handle, result));
  13.231 +        return NULL;
  13.232 +    }
  13.233 +
  13.234 +    music->freesrc = freesrc;
  13.235 +    return music;
  13.236 +}
  13.237 +
  13.238 +static void MPG123_SetVolume(void *context, int volume)
  13.239 +{
  13.240 +    MPG123_Music *music = (MPG123_Music *)context;
  13.241 +    music->volume = volume;
  13.242 +}
  13.243 +
  13.244 +static int MPG123_Play(void *context, int play_count)
  13.245 +{
  13.246 +    MPG123_Music *music = (MPG123_Music *)context;
  13.247 +    music->play_count = play_count;
  13.248 +    return MPG123_Seek(music, 0.0);
  13.249 +}
  13.250 +
  13.251 +/* read some mp3 stream data and convert it for output */
  13.252 +static int MPG123_GetSome(void *context, void *data, int bytes, SDL_bool *done)
  13.253 +{
  13.254 +    MPG123_Music *music = (MPG123_Music *)context;
  13.255 +    int filled, result;
  13.256 +    size_t amount;
  13.257 +    long rate;
  13.258 +    int channels, encoding, format;
  13.259 +
  13.260 +    if (music->stream) {
  13.261 +        filled = SDL_AudioStreamGet(music->stream, data, bytes);
  13.262 +        if (filled != 0) {
  13.263 +            return filled;
  13.264 +        }
  13.265 +    }
  13.266 +
  13.267 +    if (!music->play_count) {
  13.268 +        /* All done */
  13.269 +        *done = SDL_TRUE;
  13.270          return 0;
  13.271      }
  13.272  
  13.273 -    m->src = src;
  13.274 -    m->freesrc = freesrc;
  13.275 +    result = mpg123.mpg123_read(music->handle, music->buffer, music->buffer_size, &amount);
  13.276 +    switch (result) {
  13.277 +    case MPG123_OK:
  13.278 +        if (SDL_AudioStreamPut(music->stream, music->buffer, (int)amount) < 0) {
  13.279 +            return -1;
  13.280 +        }
  13.281 +        break;
  13.282  
  13.283 -    m->handle = mpg123.mpg123_new(0, &result);
  13.284 -    if (result != MPG123_OK) {
  13.285 -        return 0;
  13.286 +    case MPG123_NEW_FORMAT:
  13.287 +        result = mpg123.mpg123_getformat(music->handle, &rate, &channels, &encoding);
  13.288 +        if (result != MPG123_OK) {
  13.289 +            Mix_SetError("mpg123_getformat: %s", mpg_err(music->handle, result));
  13.290 +            return -1;
  13.291 +        }
  13.292 +/*printf("MPG123 format: %s, channels = %d, rate = %ld\n", mpg123_format_str(encoding), channels, rate);*/
  13.293 +
  13.294 +        format = mpg123_format_to_sdl(encoding);
  13.295 +        SDL_assert(format != -1);
  13.296 +
  13.297 +        music->stream = SDL_NewAudioStream(format, channels, (int)rate,
  13.298 +                                           music_spec.format, music_spec.channels, music_spec.freq);
  13.299 +        if (!music->stream) {
  13.300 +            return -1;
  13.301 +        }
  13.302 +        break;
  13.303 +
  13.304 +    case MPG123_DONE:
  13.305 +        if (music->play_count == 1) {
  13.306 +            music->play_count = 0;
  13.307 +            SDL_AudioStreamFlush(music->stream);
  13.308 +        } else {
  13.309 +            int play_count = -1;
  13.310 +            if (music->play_count > 0) {
  13.311 +                play_count = (music->play_count - 1);
  13.312 +            }
  13.313 +            if (MPG123_Play(music, play_count) < 0) {
  13.314 +                return -1;
  13.315 +            }
  13.316 +        }
  13.317 +        break;
  13.318 +    default:
  13.319 +        Mix_SetError("mpg123_read: %s", mpg_err(music->handle, result));
  13.320 +        return -1;
  13.321      }
  13.322 -
  13.323 -    result = mpg123.mpg123_replace_reader_handle(
  13.324 -        m->handle,
  13.325 -        rwops_read, rwops_seek, rwops_cleanup
  13.326 -   );
  13.327 -    if (result != MPG123_OK) {
  13.328 -        return 0;
  13.329 -    }
  13.330 -
  13.331 -    result = mpg123.mpg123_format_none(m->handle);
  13.332 -    if (result != MPG123_OK) {
  13.333 -        return 0;
  13.334 -    }
  13.335 -
  13.336 -    fmt = snd_format_to_mpg123(music_spec.format);
  13.337 -    if (fmt == -1) {
  13.338 -        return 0;
  13.339 -    }
  13.340 -
  13.341 -    result =  mpg123.mpg123_format(m->handle, music_spec.freq, music_spec.channels, fmt);
  13.342 -    if (result != MPG123_OK) {
  13.343 -        return 0;
  13.344 -    }
  13.345 -
  13.346 -    result = mpg123.mpg123_open_handle(m->handle, m->src);
  13.347 -    if (result != MPG123_OK) {
  13.348 -        return 0;
  13.349 -    }
  13.350 -
  13.351 -    m->volume = MIX_MAX_VOLUME;
  13.352 -    m->mixer = music_spec;
  13.353 -
  13.354 -    /* hacky: read until we can figure out the format then rewind */
  13.355 -    while (!m->gotformat)
  13.356 -    {
  13.357 -        if (!getsome(m)) {
  13.358 -            return 0;
  13.359 -        }
  13.360 -    }
  13.361 -
  13.362 -    /* rewind */
  13.363 -    mpg123.mpg123_seek(m->handle, 0, SEEK_SET);
  13.364 -
  13.365 -    m->len_available = 0;
  13.366 -    m->snd_available = m->cvt.buf;
  13.367 -
  13.368 -    return m;
  13.369 -}
  13.370 -
  13.371 -static void MPG123_SetVolume(void *context, int volume) {
  13.372 -    mpg_data* m = (mpg_data *)context;
  13.373 -    m->volume = volume;
  13.374 -}
  13.375 -
  13.376 -static int MPG123_Play(void *context)
  13.377 -{
  13.378 -    mpg_data* m = (mpg_data *)context;
  13.379 -    m->playing = SDL_TRUE;
  13.380      return 0;
  13.381  }
  13.382 -
  13.383 -static SDL_bool MPG123_IsPlaying(void *context)
  13.384 -{
  13.385 -    mpg_data* m = (mpg_data *)context;
  13.386 -    return m->playing;
  13.387 -}
  13.388 -
  13.389 -/*
  13.390 -    updates the convert struct and buffer to match the format queried from
  13.391 -    mpg123.
  13.392 -*/
  13.393 -static int update_format(mpg_data* m)
  13.394 -{
  13.395 -    int code;
  13.396 -    long rate;
  13.397 -    int channels, encoding;
  13.398 -    Uint16 sdlfmt;
  13.399 -    size_t bufsize;
  13.400 -
  13.401 -    m->gotformat = 1;
  13.402 -
  13.403 -    code =
  13.404 -        mpg123.mpg123_getformat(
  13.405 -            m->handle,
  13.406 -            &rate, &channels, &encoding
  13.407 -       );
  13.408 -
  13.409 -    if (code != MPG123_OK) {
  13.410 -        SDL_SetError("mpg123_getformat: %s", mpg_err(m->handle, code));
  13.411 -        return 0;
  13.412 -    }
  13.413 -
  13.414 -    sdlfmt = mpg123_format_to_sdl(encoding);
  13.415 -    if (sdlfmt == (Uint16)-1)
  13.416 -    {
  13.417 -        SDL_SetError(
  13.418 -            "Format %s is not supported by SDL",
  13.419 -            mpg123_format_str(encoding)
  13.420 -       );
  13.421 -        return 0;
  13.422 -    }
  13.423 -
  13.424 -    SDL_BuildAudioCVT(
  13.425 -        &m->cvt,
  13.426 -        sdlfmt, channels, (int)rate,
  13.427 -        m->mixer.format,
  13.428 -        m->mixer.channels,
  13.429 -        m->mixer.freq
  13.430 -   );
  13.431 -
  13.432 -    if (m->cvt.buf) {
  13.433 -        SDL_free(m->cvt.buf);
  13.434 -    }
  13.435 -
  13.436 -    bufsize = sizeof(m->buf) * m->cvt.len_mult;
  13.437 -    m->cvt.buf = SDL_malloc(bufsize);
  13.438 -
  13.439 -    if (!m->cvt.buf)
  13.440 -    {
  13.441 -        SDL_SetError("Out of memory");
  13.442 -        m->playing = SDL_FALSE;
  13.443 -        return 0;
  13.444 -    }
  13.445 -
  13.446 -    return 1;
  13.447 -}
  13.448 -
  13.449 -/* read some mp3 stream data and convert it for output */
  13.450 -static int getsome(mpg_data* m)
  13.451 -{
  13.452 -    int code;
  13.453 -    size_t len;
  13.454 -    Uint8* data = m->buf;
  13.455 -    size_t cbdata = sizeof(m->buf);
  13.456 -    SDL_AudioCVT* cvt = &m->cvt;
  13.457 -
  13.458 -    do
  13.459 -    {
  13.460 -        code = mpg123.mpg123_read(m->handle, data, sizeof(data), &len);
  13.461 -        switch (code)
  13.462 -        {
  13.463 -            case MPG123_NEW_FORMAT:
  13.464 -                if (!update_format(m)) {
  13.465 -                    return 0;
  13.466 -                }
  13.467 -                break;
  13.468 -
  13.469 -            case MPG123_DONE:
  13.470 -                m->playing = SDL_FALSE;
  13.471 -                break;
  13.472 -            case MPG123_OK:
  13.473 -                break;
  13.474 -
  13.475 -            default:
  13.476 -                SDL_SetError("mpg123_read: %s", mpg_err(m->handle, code));
  13.477 -                return 0;
  13.478 -        }
  13.479 -    }
  13.480 -    while (len && code != MPG123_OK);
  13.481 -
  13.482 -    SDL_memcpy(cvt->buf, data, cbdata);
  13.483 -
  13.484 -    if (cvt->needed) {
  13.485 -        /* we need to convert the audio to SDL's format */
  13.486 -        cvt->len = (int)len;
  13.487 -        SDL_ConvertAudio(cvt);
  13.488 -    }
  13.489 -
  13.490 -    else {
  13.491 -        /* no conversion needed, just copy */
  13.492 -        cvt->len_cvt = (int)len;
  13.493 -    }
  13.494 -
  13.495 -    m->len_available = cvt->len_cvt;
  13.496 -    m->snd_available = cvt->buf;
  13.497 -
  13.498 -    return 1;
  13.499 -}
  13.500 -
  13.501  static int MPG123_GetAudio(void *context, void *data, int bytes)
  13.502  {
  13.503 -    mpg_data* m = (mpg_data *)context;
  13.504 -    Uint8 *stream = (Uint8 *)data;
  13.505 -    int len = bytes;
  13.506 -    int mixable;
  13.507 -
  13.508 -    while (len > 0 && m->playing)
  13.509 -    {
  13.510 -        if (!m->len_available)
  13.511 -        {
  13.512 -            if (!getsome(m)) {
  13.513 -                m->playing = SDL_FALSE;
  13.514 -                return len;
  13.515 -            }
  13.516 -        }
  13.517 -
  13.518 -        mixable = len;
  13.519 -
  13.520 -        if (mixable > (int)m->len_available) {
  13.521 -            mixable = (int)m->len_available;
  13.522 -        }
  13.523 -
  13.524 -        if (m->volume == MIX_MAX_VOLUME) {
  13.525 -            SDL_memcpy(stream, m->snd_available, mixable);
  13.526 -        }
  13.527 -
  13.528 -        else
  13.529 -        {
  13.530 -            SDL_MixAudioFormat(
  13.531 -                stream,
  13.532 -                m->snd_available,
  13.533 -                m->mixer.format,
  13.534 -                mixable,
  13.535 -                m->volume
  13.536 -           );
  13.537 -        }
  13.538 -
  13.539 -        m->len_available -= mixable;
  13.540 -        m->snd_available += mixable;
  13.541 -        len -= mixable;
  13.542 -        stream += mixable;
  13.543 -    }
  13.544 -
  13.545 -    return len;
  13.546 +    MPG123_Music *music = (MPG123_Music *)context;
  13.547 +    return music_pcm_getaudio(context, data, bytes, music->volume, MPG123_GetSome);
  13.548  }
  13.549  
  13.550  static int MPG123_Seek(void *context, double secs)
  13.551  {
  13.552 -    mpg_data* m = (mpg_data *)context;
  13.553 -    off_t offset = (off_t)(m->mixer.freq * secs);
  13.554 +    MPG123_Music *music = (MPG123_Music *)context;
  13.555 +    off_t offset = (off_t)(music_spec.freq * secs);
  13.556  
  13.557 -    if ((offset = mpg123.mpg123_seek(m->handle, offset, SEEK_SET)) < 0) {
  13.558 -        return Mix_SetError("mpg123_seek: %s", mpg_err(m->handle, (int)-offset));
  13.559 +    if ((offset = mpg123.mpg123_seek(music->handle, offset, SEEK_SET)) < 0) {
  13.560 +        return Mix_SetError("mpg123_seek: %s", mpg_err(music->handle, (int)-offset));
  13.561      }
  13.562      return 0;
  13.563  }
  13.564  
  13.565 -static void MPG123_Stop(void *context)
  13.566 -{
  13.567 -    mpg_data* m = (mpg_data *)context;
  13.568 -    m->playing = SDL_FALSE;
  13.569 -}
  13.570 -
  13.571  static void MPG123_Delete(void *context)
  13.572  {
  13.573 -    mpg_data* m = (mpg_data *)context;
  13.574 +    MPG123_Music *music = (MPG123_Music *)context;
  13.575  
  13.576 -    if (m->freesrc) {
  13.577 -        SDL_RWclose(m->src);
  13.578 +    if (music->handle) {
  13.579 +        mpg123.mpg123_close(music->handle);
  13.580 +        mpg123.mpg123_delete(music->handle);
  13.581      }
  13.582 -
  13.583 -    if (m->cvt.buf) {
  13.584 -        SDL_free(m->cvt.buf);
  13.585 +    if (music->stream) {
  13.586 +        SDL_FreeAudioStream(music->stream);
  13.587      }
  13.588 -
  13.589 -    mpg123.mpg123_close(m->handle);
  13.590 -    mpg123.mpg123_delete(m->handle);
  13.591 -    SDL_free(m);
  13.592 +    if (music->buffer) {
  13.593 +        SDL_free(music->buffer);
  13.594 +    }
  13.595 +    if (music->freesrc) {
  13.596 +        SDL_RWclose(music->src);
  13.597 +    }
  13.598 +    SDL_free(music);
  13.599  }
  13.600  
  13.601  static void MPG123_Close(void)
  13.602 @@ -527,12 +416,12 @@
  13.603      NULL,   /* CreateFromFile */
  13.604      MPG123_SetVolume,
  13.605      MPG123_Play,
  13.606 -    MPG123_IsPlaying,
  13.607 +    NULL,   /* IsPlaying */
  13.608      MPG123_GetAudio,
  13.609      MPG123_Seek,
  13.610      NULL,   /* Pause */
  13.611      NULL,   /* Resume */
  13.612 -    MPG123_Stop,
  13.613 +    NULL,   /* Stop */
  13.614      MPG123_Delete,
  13.615      MPG123_Close,
  13.616      MPG123_Unload
    14.1 --- a/music_nativemidi.c	Fri Oct 20 21:55:03 2017 -0700
    14.2 +++ b/music_nativemidi.c	Fri Oct 20 23:39:04 2017 -0700
    14.3 @@ -36,10 +36,14 @@
    14.4      return music;
    14.5  }
    14.6  
    14.7 -static int NATIVEMIDI_Play(void *context)
    14.8 +static int NATIVEMIDI_Play(void *context, int play_count)
    14.9  {
   14.10      NativeMidiSong *music = (NativeMidiSong *)context;
   14.11 -    native_midi_start(music, music_loops);
   14.12 +    int loops = play_count;
   14.13 +    if (loops > 0) {
   14.14 +        --loops;
   14.15 +    }
   14.16 +    native_midi_start(music, loops);
   14.17      return 0;
   14.18  }
   14.19  
    15.1 --- a/music_ogg.c	Fri Oct 20 21:55:03 2017 -0700
    15.2 +++ b/music_ogg.c	Fri Oct 20 23:39:04 2017 -0700
    15.3 @@ -204,13 +204,14 @@
    15.4  typedef struct {
    15.5      SDL_RWops *src;
    15.6      int freesrc;
    15.7 -    SDL_bool playing;
    15.8 +    int play_count;
    15.9      int volume;
   15.10      OggVorbis_File vf;
   15.11 +    vorbis_info vi;
   15.12      int section;
   15.13 -    SDL_AudioCVT cvt;
   15.14 -    int len_available;
   15.15 -    Uint8 *snd_available;
   15.16 +    SDL_AudioStream *stream;
   15.17 +    char *buffer;
   15.18 +    int buffer_size;
   15.19      int loop;
   15.20      ogg_int64_t loop_start;
   15.21      ogg_int64_t loop_end;
   15.22 @@ -218,6 +219,32 @@
   15.23      ogg_int64_t channels;
   15.24  } OGG_music;
   15.25  
   15.26 +
   15.27 +static int set_ov_error(const char *function, int error)
   15.28 +{
   15.29 +#define HANDLE_ERROR_CASE(X)    case X: Mix_SetError("%s: %s", function, #X); break;
   15.30 +    switch (error) {
   15.31 +    HANDLE_ERROR_CASE(OV_FALSE);
   15.32 +    HANDLE_ERROR_CASE(OV_EOF);
   15.33 +    HANDLE_ERROR_CASE(OV_HOLE);
   15.34 +    HANDLE_ERROR_CASE(OV_EREAD);
   15.35 +    HANDLE_ERROR_CASE(OV_EFAULT);
   15.36 +    HANDLE_ERROR_CASE(OV_EIMPL);
   15.37 +    HANDLE_ERROR_CASE(OV_EINVAL);
   15.38 +    HANDLE_ERROR_CASE(OV_ENOTVORBIS);
   15.39 +    HANDLE_ERROR_CASE(OV_EBADHEADER);
   15.40 +    HANDLE_ERROR_CASE(OV_EVERSION);
   15.41 +    HANDLE_ERROR_CASE(OV_ENOTAUDIO);
   15.42 +    HANDLE_ERROR_CASE(OV_EBADPACKET);
   15.43 +    HANDLE_ERROR_CASE(OV_EBADLINK);
   15.44 +    HANDLE_ERROR_CASE(OV_ENOSEEK);
   15.45 +    default:
   15.46 +        Mix_SetError("%s: unknown error %d\n", function, error);
   15.47 +        break;
   15.48 +    }
   15.49 +    return -1;
   15.50 +}
   15.51 +
   15.52  static size_t sdl_read_func(void *ptr, size_t size, size_t nmemb, void *datasource)
   15.53  {
   15.54      return SDL_RWread((SDL_RWops*)datasource, ptr, size, nmemb);
   15.55 @@ -233,99 +260,126 @@
   15.56      return (long)SDL_RWtell((SDL_RWops*)datasource);
   15.57  }
   15.58  
   15.59 +static int OGG_Seek(void *context, double time);
   15.60 +static void OGG_Delete(void *context);
   15.61 +
   15.62 +static int OGG_UpdateSection(OGG_music *music)
   15.63 +{
   15.64 +    vorbis_info *vi;
   15.65 +
   15.66 +    vi = vorbis.ov_info(&music->vf, -1);
   15.67 +    if (!vi) {
   15.68 +        Mix_SetError("ov_info returned NULL");
   15.69 +        return -1;
   15.70 +    }
   15.71 +
   15.72 +    if (vi->channels == music->vi.channels && vi->rate == music->vi.rate) {
   15.73 +        return 0;
   15.74 +    }
   15.75 +    SDL_memcpy(&music->vi, vi, sizeof(*vi));
   15.76 +
   15.77 +    if (music->buffer) {
   15.78 +        SDL_free(music->buffer);
   15.79 +        music->buffer = NULL;
   15.80 +    }
   15.81 +
   15.82 +    if (music->stream) {
   15.83 +        SDL_FreeAudioStream(music->stream);
   15.84 +        music->stream = NULL;
   15.85 +    }
   15.86 +
   15.87 +    music->stream = SDL_NewAudioStream(AUDIO_S16, vi->channels, (int)vi->rate,
   15.88 +                                       music_spec.format, music_spec.channels, music_spec.freq);
   15.89 +    if (!music->stream) {
   15.90 +        return -1;
   15.91 +    }
   15.92 +
   15.93 +    music->buffer_size = music_spec.samples * sizeof(Sint16) * vi->channels;
   15.94 +    music->buffer = (char *)SDL_malloc(music->buffer_size);
   15.95 +    if (!music->buffer) {
   15.96 +        return -1;
   15.97 +    }
   15.98 +    return 0;
   15.99 +}
  15.100 +
  15.101  /* Load an OGG stream from an SDL_RWops object */
  15.102  static void *OGG_CreateFromRW(SDL_RWops *src, int freesrc)
  15.103  {
  15.104      OGG_music *music;
  15.105      ov_callbacks callbacks;
  15.106 +    vorbis_comment *vc;
  15.107 +    int isLoopLength = 0, i;
  15.108 +    ogg_int64_t fullLength;
  15.109  
  15.110 -    SDL_memset(&callbacks, 0, sizeof(callbacks));
  15.111 +    music = (OGG_music *)SDL_calloc(1, sizeof *music);
  15.112 +    if (!music) {
  15.113 +        SDL_OutOfMemory();
  15.114 +        return NULL;
  15.115 +    }
  15.116 +    music->src = src;
  15.117 +    music->volume = MIX_MAX_VOLUME;
  15.118 +    music->section = -1;
  15.119 +    music->loop = -1;
  15.120 +    music->loop_start = -1;
  15.121 +    music->loop_end = 0;
  15.122 +    music->loop_len = 0;
  15.123 +
  15.124 +    SDL_zero(callbacks);
  15.125      callbacks.read_func = sdl_read_func;
  15.126      callbacks.seek_func = sdl_seek_func;
  15.127      callbacks.tell_func = sdl_tell_func;
  15.128  
  15.129 -    music = (OGG_music *)SDL_calloc(1, sizeof *music);
  15.130 -    if (music) {
  15.131 -        vorbis_info *vi;
  15.132 -        vorbis_comment *vc;
  15.133 -        int isLoopLength = 0, i;
  15.134 -        ogg_int64_t fullLength;
  15.135 +    if (vorbis.ov_open_callbacks(src, &music->vf, NULL, 0, callbacks) < 0) {
  15.136 +        SDL_SetError("Not an Ogg Vorbis audio stream");
  15.137 +        SDL_free(music);
  15.138 +        return NULL;
  15.139 +    }
  15.140  
  15.141 -        /* Initialize the music structure */
  15.142 -        music->src = src;
  15.143 -        music->freesrc = freesrc;
  15.144 -        music->volume = MIX_MAX_VOLUME;
  15.145 -        music->section = -1;
  15.146 +    if (OGG_UpdateSection(music) < 0) {
  15.147 +        OGG_Delete(music);
  15.148 +        return NULL;
  15.149 +    }
  15.150  
  15.151 -        music->loop         = -1;
  15.152 -        music->loop_start   = -1;
  15.153 -        music->loop_end     =  0;
  15.154 -        music->loop_len     =  0;
  15.155 -
  15.156 -        if (vorbis.ov_open_callbacks(src, &music->vf, NULL, 0, callbacks) < 0) {
  15.157 -            SDL_SetError("Not an Ogg Vorbis audio stream");
  15.158 -            SDL_free(music);
  15.159 -            return NULL;
  15.160 +    vc = vorbis.ov_comment(&music->vf, -1);
  15.161 +    for (i = 0; i < vc->comments; i++) {
  15.162 +        char *param = SDL_strdup(vc->user_comments[i]);
  15.163 +        char *argument = param;
  15.164 +        char *value = SDL_strchr(param, '=');
  15.165 +        if (value == NULL) {
  15.166 +            value = param + SDL_strlen(param);
  15.167 +        } else {
  15.168 +            *(value++) = '\0';
  15.169          }
  15.170  
  15.171 -        vi = vorbis.ov_info(&music->vf, -1);
  15.172 -        music->channels = vi->channels;
  15.173 +        if (SDL_strcasecmp(argument, "LOOPSTART") == 0)
  15.174 +            music->loop_start = SDL_strtoull(value, NULL, 0);
  15.175 +        else if (SDL_strcasecmp(argument, "LOOPLENGTH") == 0) {
  15.176 +            music->loop_len = SDL_strtoull(value, NULL, 0);
  15.177 +            isLoopLength = 1;
  15.178 +        } else if (SDL_strcasecmp(argument, "LOOPEND") == 0) {
  15.179 +            isLoopLength = 0;
  15.180 +            music->loop_end = SDL_strtoull(value, NULL, 0);
  15.181 +        }
  15.182 +        SDL_free(param);
  15.183 +    }
  15.184  
  15.185 -        vc = vorbis.ov_comment(&music->vf, -1);
  15.186 +    if (isLoopLength == 1) {
  15.187 +        music->loop_end = music->loop_start + music->loop_len;
  15.188 +    } else {
  15.189 +        music->loop_len = music->loop_end - music->loop_start;
  15.190 +    }
  15.191  
  15.192 -        for (i = 0; i < vc->comments; i++) {
  15.193 -            int   paramLen = vc->comment_lengths[i] + 1;
  15.194 -            char *param = (char *)SDL_malloc((size_t)paramLen);
  15.195 -            char *argument  = param;
  15.196 -            char *value     = param;
  15.197 -            SDL_memset(param, 0, (size_t)paramLen);
  15.198 -            SDL_memcpy(param, vc->user_comments[i], (size_t)vc->comment_lengths[i]);
  15.199 -            value = SDL_strchr(param, '=');
  15.200 -            if (value == NULL) {
  15.201 -                value = param + paramLen - 1; /* set null */
  15.202 -            } else {
  15.203 -                *(value++) = '\0';
  15.204 -            }
  15.205 +    fullLength = vorbis.ov_pcm_total(&music->vf, -1);
  15.206 +    if (((music->loop_start >= 0) || (music->loop_end > 0)) &&
  15.207 +        ((music->loop_start < music->loop_end) || (music->loop_end == 0)) &&
  15.208 +         (music->loop_start < fullLength) &&
  15.209 +         (music->loop_end <= fullLength)) {
  15.210 +        if (music->loop_start < 0) music->loop_start = 0;
  15.211 +        if (music->loop_end == 0)  music->loop_end = fullLength;
  15.212 +        music->loop = 1;
  15.213 +    }
  15.214  
  15.215 -            #ifdef __USE_ISOC99
  15.216 -            #define A_TO_OGG64(x) (ogg_int64_t)atoll(x)
  15.217 -            #else
  15.218 -            #define A_TO_OGG64(x) (ogg_int64_t)atol(x)
  15.219 -            #endif
  15.220 -
  15.221 -            if (SDL_strcasecmp(argument, "LOOPSTART") == 0)
  15.222 -                music->loop_start = A_TO_OGG64(value);
  15.223 -            else if (SDL_strcasecmp(argument, "LOOPLENGTH") == 0) {
  15.224 -                music->loop_len = A_TO_OGG64(value);
  15.225 -                isLoopLength = 1;
  15.226 -            }
  15.227 -            else if (SDL_strcasecmp(argument, "LOOPEND") == 0) {
  15.228 -                isLoopLength = 0;
  15.229 -                music->loop_end = A_TO_OGG64(value);
  15.230 -            }
  15.231 -
  15.232 -            #undef A_TO_OGG64
  15.233 -            SDL_free(param);
  15.234 -        }
  15.235 -
  15.236 -        if (isLoopLength == 1)
  15.237 -            music->loop_end = music->loop_start + music->loop_len;
  15.238 -        else
  15.239 -            music->loop_len = music->loop_end - music->loop_start;
  15.240 -
  15.241 -        fullLength = vorbis.ov_pcm_total(&music->vf, -1);
  15.242 -        if (((music->loop_start >= 0) || (music->loop_end > 0)) &&
  15.243 -            ((music->loop_start < music->loop_end) || (music->loop_end == 0)) &&
  15.244 -             (music->loop_start < fullLength) &&
  15.245 -             (music->loop_end <= fullLength)) {
  15.246 -            if (music->loop_start < 0) music->loop_start = 0;
  15.247 -            if (music->loop_end == 0)  music->loop_end = fullLength;
  15.248 -            music->loop = 1;
  15.249 -        }
  15.250 -
  15.251 -    } else {
  15.252 -        SDL_OutOfMemory();
  15.253 -    }
  15.254 +    music->freesrc = freesrc;
  15.255      return music;
  15.256  }
  15.257  
  15.258 @@ -337,139 +391,119 @@
  15.259  }
  15.260  
  15.261  /* Start playback of a given OGG stream */
  15.262 -static int OGG_Play(void *context)
  15.263 +static int OGG_Play(void *context, int play_count)
  15.264  {
  15.265      OGG_music *music = (OGG_music *)context;
  15.266 -    music->playing = SDL_TRUE;
  15.267 -    return 0;
  15.268 +    music->play_count = play_count;
  15.269 +    return OGG_Seek(music, 0.0);
  15.270  }
  15.271  
  15.272 -/* Return non-zero if a stream is currently playing */
  15.273 -static SDL_bool OGG_IsPlaying(void *context)
  15.274 +/* Play some of a stream previously started with OGG_play() */
  15.275 +static int OGG_GetSome(void *context, void *data, int bytes, SDL_bool *done)
  15.276  {
  15.277      OGG_music *music = (OGG_music *)context;
  15.278 -    return music->playing;
  15.279 -}
  15.280 +    SDL_bool looped = SDL_FALSE;
  15.281 +    int filled, amount, result;
  15.282 +    int section;
  15.283 +    ogg_int64_t pcmPos;
  15.284  
  15.285 -/* Read some Ogg stream data and convert it for output */
  15.286 -static void OGG_getsome(OGG_music *music)
  15.287 -{
  15.288 -    int section;
  15.289 -    int len;
  15.290 -    char data[4096];
  15.291 -    ogg_int64_t pcmPos;
  15.292 -    SDL_AudioCVT *cvt;
  15.293 +    filled = SDL_AudioStreamGet(music->stream, data, bytes);
  15.294 +    if (filled != 0) {
  15.295 +        return filled;
  15.296 +    }
  15.297  
  15.298 +    if (!music->play_count) {
  15.299 +        /* All done */
  15.300 +        *done = SDL_TRUE;
  15.301 +        return 0;
  15.302 +    }
  15.303 +
  15.304 +    section = music->section;
  15.305  #ifdef OGG_USE_TREMOR
  15.306 -    len = vorbis.ov_read(&music->vf, data, sizeof(data), &section);
  15.307 +    amount = vorbis.ov_read(&music->vf, music->buffer, music->buffer_size, &section);
  15.308  #else
  15.309 -    len = (int)vorbis.ov_read(&music->vf, data, sizeof(data), 0, 2, 1, &section);
  15.310 +    amount = (int)vorbis.ov_read(&music->vf, music->buffer, music->buffer_size, 0, 2, 1, &section);
  15.311  #endif
  15.312 +    if (amount < 0) {
  15.313 +        set_ov_error("ov_read", amount);
  15.314 +        return -1;
  15.315 +    }
  15.316 +
  15.317 +    if (section != music->section) {
  15.318 +        music->section = section;
  15.319 +        if (OGG_UpdateSection(music) < 0) {
  15.320 +            return -1;
  15.321 +        }
  15.322 +    }
  15.323  
  15.324      pcmPos = vorbis.ov_pcm_tell(&music->vf);
  15.325      if ((music->loop == 1) && (pcmPos >= music->loop_end)) {
  15.326 -        len -= ((pcmPos - music->loop_end) * music->channels) * (long)sizeof(Uint16);
  15.327 -        vorbis.ov_pcm_seek(&music->vf, music->loop_start);
  15.328 +        amount -= ((pcmPos - music->loop_end) * music->channels) * (long)sizeof(Sint16);
  15.329 +        result = vorbis.ov_pcm_seek(&music->vf, music->loop_start);
  15.330 +        if (result < 0) {
  15.331 +            set_ov_error("ov_pcm_seek", result);
  15.332 +            return -1;
  15.333 +        }
  15.334 +        looped = SDL_TRUE;
  15.335      }
  15.336  
  15.337 -    if (len <= 0) {
  15.338 -        if (len == 0) {
  15.339 -            music->playing = SDL_FALSE;
  15.340 +    if (amount > 0) {
  15.341 +        if (SDL_AudioStreamPut(music->stream, music->buffer, amount) < 0) {
  15.342 +            return -1;
  15.343          }
  15.344 -        return;
  15.345 +    } else if (!looped) {
  15.346 +        if (music->play_count == 1) {
  15.347 +            music->play_count = 0;
  15.348 +            SDL_AudioStreamFlush(music->stream);
  15.349 +        } else {
  15.350 +            int play_count = -1;
  15.351 +            if (music->play_count > 0) {
  15.352 +                play_count = (music->play_count - 1);
  15.353 +            }
  15.354 +            if (OGG_Play(music, play_count) < 0) {
  15.355 +                return -1;
  15.356 +            }
  15.357 +        }
  15.358      }
  15.359 -    cvt = &music->cvt;
  15.360 -    if (section != music->section) {
  15.361 -        vorbis_info *vi;
  15.362 -
  15.363 -        vi = vorbis.ov_info(&music->vf, -1);
  15.364 -        SDL_BuildAudioCVT(cvt, AUDIO_S16, vi->channels, (int)vi->rate,
  15.365 -                               music_spec.format, music_spec.channels, music_spec.freq);
  15.366 -        if (cvt->buf) {
  15.367 -            SDL_free(cvt->buf);
  15.368 -        }
  15.369 -        cvt->buf = (Uint8 *)SDL_malloc(sizeof(data)*cvt->len_mult);
  15.370 -        music->section = section;
  15.371 -    }
  15.372 -    if (cvt->buf) {
  15.373 -        SDL_memcpy(cvt->buf, data, len);
  15.374 -        if (cvt->needed) {
  15.375 -            cvt->len = len;
  15.376 -            SDL_ConvertAudio(cvt);
  15.377 -        } else {
  15.378 -            cvt->len_cvt = len;
  15.379 -        }
  15.380 -        music->len_available = music->cvt.len_cvt;
  15.381 -        music->snd_available = music->cvt.buf;
  15.382 -    } else {
  15.383 -        SDL_SetError("Out of memory");
  15.384 -        music->playing = SDL_FALSE;
  15.385 -    }
  15.386 +    return 0;
  15.387  }
  15.388 -
  15.389 -/* Play some of a stream previously started with OGG_play() */
  15.390  static int OGG_GetAudio(void *context, void *data, int bytes)
  15.391  {
  15.392      OGG_music *music = (OGG_music *)context;
  15.393 -    Uint8 *snd = (Uint8 *)data;
  15.394 -    int len = bytes;
  15.395 -    int mixable;
  15.396 -
  15.397 -    while ((len > 0) && music->playing) {
  15.398 -        if (!music->len_available) {
  15.399 -            OGG_getsome(music);
  15.400 -        }
  15.401 -        mixable = len;
  15.402 -        if (mixable > music->len_available) {
  15.403 -            mixable = music->len_available;
  15.404 -        }
  15.405 -        if (music->volume == MIX_MAX_VOLUME) {
  15.406 -            SDL_memcpy(snd, music->snd_available, mixable);
  15.407 -        } else {
  15.408 -            SDL_MixAudioFormat(snd, music->snd_available, music_spec.format, mixable, music->volume);
  15.409 -        }
  15.410 -        music->len_available -= mixable;
  15.411 -        music->snd_available += mixable;
  15.412 -        len -= mixable;
  15.413 -        snd += mixable;
  15.414 -    }
  15.415 -
  15.416 -    return len;
  15.417 +    return music_pcm_getaudio(context, data, bytes, music->volume, OGG_GetSome);
  15.418  }
  15.419  
  15.420  /* Jump (seek) to a given position (time is in seconds) */
  15.421  static int OGG_Seek(void *context, double time)
  15.422  {
  15.423      OGG_music *music = (OGG_music *)context;
  15.424 +    int result;
  15.425  #ifdef OGG_USE_TREMOR
  15.426 -    vorbis.ov_time_seek(&music->vf, (ogg_int64_t)(time * 1000.0));
  15.427 +    result = vorbis.ov_time_seek(&music->vf, (ogg_int64_t)(time * 1000.0));
  15.428  #else
  15.429 -    vorbis.ov_time_seek(&music->vf, time);
  15.430 +    result = vorbis.ov_time_seek(&music->vf, time);
  15.431  #endif
  15.432 +    if (result < 0) {
  15.433 +        return set_ov_error("ov_time_seek", result);
  15.434 +    }
  15.435      return 0;
  15.436  }
  15.437  
  15.438 -/* Stop playback of a stream previously started with OGG_play() */
  15.439 -static void OGG_Stop(void *context)
  15.440 -{
  15.441 -    OGG_music *music = (OGG_music *)context;
  15.442 -    music->playing = SDL_FALSE;
  15.443 -}
  15.444 -
  15.445  /* Close the given OGG stream */
  15.446  static void OGG_Delete(void *context)
  15.447  {
  15.448      OGG_music *music = (OGG_music *)context;
  15.449 -    if (music) {
  15.450 -        if (music->cvt.buf) {
  15.451 -            SDL_free(music->cvt.buf);
  15.452 -        }
  15.453 -        if (music->freesrc) {
  15.454 -            SDL_RWclose(music->src);
  15.455 -        }
  15.456 -        vorbis.ov_clear(&music->vf);
  15.457 -        SDL_free(music);
  15.458 +    vorbis.ov_clear(&music->vf);
  15.459 +    if (music->stream) {
  15.460 +        SDL_FreeAudioStream(music->stream);
  15.461      }
  15.462 +    if (music->buffer) {
  15.463 +        SDL_free(music->buffer);
  15.464 +    }
  15.465 +    if (music->freesrc) {
  15.466 +        SDL_RWclose(music->src);
  15.467 +    }
  15.468 +    SDL_free(music);
  15.469  }
  15.470  
  15.471  Mix_MusicInterface Mix_MusicInterface_OGG =
  15.472 @@ -486,12 +520,12 @@
  15.473      NULL,   /* CreateFromFile */
  15.474      OGG_SetVolume,
  15.475      OGG_Play,
  15.476 -    OGG_IsPlaying,
  15.477 +    NULL,   /* IsPlaying */
  15.478      OGG_GetAudio,
  15.479      OGG_Seek,
  15.480      NULL,   /* Pause */
  15.481      NULL,   /* Resume */
  15.482 -    OGG_Stop,
  15.483 +    NULL,   /* Stop */
  15.484      OGG_Delete,
  15.485      NULL,   /* Close */
  15.486      OGG_Unload,
    16.1 --- a/music_smpeg.c	Fri Oct 20 21:55:03 2017 -0700
    16.2 +++ b/music_smpeg.c	Fri Oct 20 23:39:04 2017 -0700
    16.3 @@ -210,70 +210,98 @@
    16.4  #endif /* SMPEG_DYNAMIC */
    16.5  
    16.6  
    16.7 +typedef struct
    16.8 +{
    16.9 +    SMPEG *mp3;
   16.10 +    SDL_RWops *src;
   16.11 +    int freesrc;
   16.12 +} SMPEG_Music;
   16.13 +
   16.14  static void *SMPEG_CreateFromRW(SDL_RWops *src, int freesrc)
   16.15  {
   16.16 +    SMPEG_Music *music;
   16.17      SMPEG_Info info;
   16.18 -    SMPEG *mp3 = smpeg.SMPEG_new_rwops(src, &info, freesrc, 0);
   16.19 +
   16.20 +    music = (SMPEG_Music *)SDL_calloc(1, sizeof(*music));
   16.21 +    if (!music) {
   16.22 +        SDL_OutOfMemory();
   16.23 +        return NULL;
   16.24 +    }
   16.25 +    music->src = src;
   16.26 +
   16.27 +    music->mp3 = smpeg.SMPEG_new_rwops(src, &info, SDL_FALSE, 0);
   16.28      if (!info.has_audio) {
   16.29          Mix_SetError("MPEG file does not have any audio stream.");
   16.30 -        smpeg.SMPEG_delete(mp3);
   16.31 +        smpeg.SMPEG_delete(music->mp3);
   16.32 +        SDL_free(music);
   16.33          return NULL;
   16.34      }
   16.35      smpeg.SMPEG_actualSpec(mp3, &music_spec);
   16.36 -    return mp3;
   16.37 +
   16.38 +    music->freesrc = freesrc;
   16.39 +    return music;
   16.40  }
   16.41  
   16.42  static void SMPEG_SetVolume(void *context, int volume)
   16.43  {
   16.44 -    SMPEG *mp3 = (SMPEG *)context;
   16.45 -    smpeg.SMPEG_setvolume(mp3,(int)(((float)volume/(float)MIX_MAX_VOLUME)*100.0));
   16.46 +    SMPEG_Music *music = (SMPEG_Music *)context;
   16.47 +    smpeg.SMPEG_setvolume(music->mp3,(int)(((float)volume/(float)MIX_MAX_VOLUME)*100.0));
   16.48  }
   16.49  
   16.50  static int SMPEG_Play(void *context)
   16.51  {
   16.52 -    SMPEG *mp3 = (SMPEG *)context;
   16.53 -    smpeg.SMPEG_enableaudio(mp3,1);
   16.54 -    smpeg.SMPEG_enablevideo(mp3,0);
   16.55 -    smpeg.SMPEG_play(mp3);
   16.56 +    SMPEG_Music *music = (SMPEG_Music *)context;
   16.57 +    smpeg.SMPEG_enableaudio(music->mp3, 1);
   16.58 +    smpeg.SMPEG_enablevideo(music->mp3, 0);
   16.59 +    smpeg.SMPEG_rewind(music->mp3);
   16.60 +    smpeg.SMPEG_play(music->mp3);
   16.61      return 0;
   16.62  }
   16.63  
   16.64  static SDL_bool SMPEG_IsPlaying(void *context)
   16.65  {
   16.66 -    SMPEG *mp3 = (SMPEG *)context;
   16.67 -    return smpeg.SMPEG_status(mp3) == SMPEG_PLAYING ? SDL_TRUE : SDL_FALSE;
   16.68 +    SMPEG_Music *music = (SMPEG_Music *)context;
   16.69 +    return smpeg.SMPEG_status(music->mp3) == SMPEG_PLAYING ? SDL_TRUE : SDL_FALSE;
   16.70  }
   16.71  
   16.72  static int SMPEG_GetAudio(void *context, void *data, int bytes)
   16.73  {
   16.74 -    SMPEG *mp3 = (SMPEG *)context;
   16.75 +    SMPEG_Music *music = (SMPEG_Music *)context;
   16.76      Uint8 *stream = (Uint8 *)data;
   16.77      int len = bytes;
   16.78 -    int left = (len - smpeg.SMPEG_playAudio(mp3, stream, len));
   16.79 +    int left = (len - smpeg.SMPEG_playAudio(music->mp3, stream, len));
   16.80 +    if (left > 0) {
   16.81 +        stream += (len - left);
   16.82      return left;
   16.83  }
   16.84  
   16.85  static int SMPEG_Seek(void *context, double position)
   16.86  {
   16.87 -    SMPEG *mp3 = (SMPEG *)context;
   16.88 -    smpeg.SMPEG_rewind(mp3);
   16.89 -    smpeg.SMPEG_play(mp3);
   16.90 +    SMPEG_Music *music = (SMPEG_Music *)context;
   16.91 +    smpeg.SMPEG_rewind(music->mp3);
   16.92 +    smpeg.SMPEG_play(music->mp3);
   16.93      if (position > 0.0) {
   16.94 -        smpeg.SMPEG_skip(mp3, (float)position);
   16.95 +        smpeg.SMPEG_skip(music->mp3, (float)position);
   16.96      }
   16.97      return 0;
   16.98  }
   16.99  
  16.100  static void SMPEG_Stop(void *context)
  16.101  {
  16.102 -    SMPEG *mp3 = (SMPEG *)context;
  16.103 -    smpeg.SMPEG_stop(mp3);
  16.104 +    SMPEG_Music *music = (SMPEG_Music *)context;
  16.105 +    smpeg.SMPEG_stop(music->mp3);
  16.106  }
  16.107  
  16.108  static void SMPEG_Delete(void *context)
  16.109  {
  16.110 -    SMPEG *mp3 = (SMPEG *)context;
  16.111 -    smpeg.SMPEG_delete(mp3);
  16.112 +    SMPEG_Music *music = (SMPEG_Music *)context;
  16.113 +
  16.114 +    smpeg.SMPEG_delete(music->mp3);
  16.115 +
  16.116 +    if (music->freesrc) {
  16.117 +        SDL_RWclose(music->src);
  16.118 +    }
  16.119 +    SDL_free(music);
  16.120  }
  16.121  
  16.122  Mix_MusicInterface Mix_MusicInterface_SMPEG =
    17.1 --- a/music_timidity.c	Fri Oct 20 21:55:03 2017 -0700
    17.2 +++ b/music_timidity.c	Fri Oct 20 23:39:04 2017 -0700
    17.3 @@ -28,6 +28,15 @@
    17.4  #include "timidity/timidity.h"
    17.5  
    17.6  
    17.7 +typedef struct
    17.8 +{
    17.9 +    int play_count;
   17.10 +    MidiSong *song;
   17.11 +} TIMIDITY_Music;
   17.12 +
   17.13 +
   17.14 +static int TIMIDITY_Seek(void *context, double position);
   17.15 +
   17.16  static int TIMIDITY_Open(const SDL_AudioSpec *spec)
   17.17  {
   17.18      return Timidity_Init();
   17.19 @@ -40,8 +49,21 @@
   17.20  
   17.21  void *TIMIDITY_CreateFromRW(SDL_RWops *src, int freesrc)
   17.22  {
   17.23 -    MidiSong *music = Timidity_LoadSong(src, &music_spec);
   17.24 -    if (music && freesrc) {
   17.25 +    TIMIDITY_Music *music;
   17.26 +
   17.27 +    music = (TIMIDITY_Music *)SDL_calloc(1, sizeof(*music));
   17.28 +    if (!music) {
   17.29 +        SDL_OutOfMemory();
   17.30 +        return NULL;
   17.31 +    }
   17.32 +
   17.33 +    music->song = Timidity_LoadSong(src, &music_spec);
   17.34 +    if (!music->song) {
   17.35 +        SDL_free(music);
   17.36 +        return NULL;
   17.37 +    }
   17.38 +
   17.39 +    if (freesrc) {
   17.40          SDL_RWclose(src);
   17.41      }
   17.42      return music;
   17.43 @@ -49,38 +71,51 @@
   17.44  
   17.45  static void TIMIDITY_SetVolume(void *context, int volume)
   17.46  {
   17.47 -    MidiSong *music = (MidiSong *)context;
   17.48 -    Timidity_SetVolume(music, volume);
   17.49 +    TIMIDITY_Music *music = (TIMIDITY_Music *)context;
   17.50 +    Timidity_SetVolume(music->song, volume);
   17.51  }
   17.52  
   17.53 -static int TIMIDITY_Play(void *context)
   17.54 +static int TIMIDITY_Play(void *context, int play_count)
   17.55  {
   17.56 -    MidiSong *music = (MidiSong *)context;
   17.57 -    Timidity_Start(music);
   17.58 -    return 0;
   17.59 +    TIMIDITY_Music *music = (TIMIDITY_Music *)context;
   17.60 +    music->play_count = play_count;
   17.61 +    Timidity_Start(music->song);
   17.62 +    return TIMIDITY_Seek(music, 0.0);
   17.63  }
   17.64  
   17.65  static int TIMIDITY_GetAudio(void *context, void *data, int bytes)
   17.66  {
   17.67 -    MidiSong *music = (MidiSong *)context;
   17.68 -    if (!Timidity_PlaySome(music, data, bytes)) {
   17.69 -        /* Nothing consumed, everything left */
   17.70 -        return bytes;
   17.71 +    TIMIDITY_Music *music = (TIMIDITY_Music *)context;
   17.72 +    if (!Timidity_PlaySome(music->song, data, bytes)) {
   17.73 +        if (music->play_count == 1) {
   17.74 +            /* We didn't consume anything and we're done */
   17.75 +            music->play_count = 0;
   17.76 +            return bytes;
   17.77 +        } else {
   17.78 +            int play_count = -1;
   17.79 +            if (music->play_count > 0) {
   17.80 +                play_count = (music->play_count - 1);
   17.81 +            }
   17.82 +            if (TIMIDITY_Play(music, play_count) < 0) {
   17.83 +                return -1;
   17.84 +            }
   17.85 +        }
   17.86      }
   17.87      return 0;
   17.88  }
   17.89  
   17.90  static int TIMIDITY_Seek(void *context, double position)
   17.91  {
   17.92 -    MidiSong *music = (MidiSong *)context;
   17.93 -    Timidity_Seek(music, (Uint32)(position * 1000));
   17.94 +    TIMIDITY_Music *music = (TIMIDITY_Music *)context;
   17.95 +    Timidity_Seek(music->song, (Uint32)(position * 1000));
   17.96      return 0;
   17.97  }
   17.98  
   17.99  static void TIMIDITY_Delete(void *context)
  17.100  {
  17.101 -    MidiSong *music = (MidiSong *)context;
  17.102 -    Timidity_FreeSong(music);
  17.103 +    TIMIDITY_Music *music = (TIMIDITY_Music *)context;
  17.104 +    Timidity_FreeSong(music->song);
  17.105 +    SDL_free(music);
  17.106  }
  17.107  
  17.108  Mix_MusicInterface Mix_MusicInterface_TIMIDITY =
    18.1 --- a/music_wav.c	Fri Oct 20 21:55:03 2017 -0700
    18.2 +++ b/music_wav.c	Fri Oct 20 23:39:04 2017 -0700
    18.3 @@ -39,12 +39,14 @@
    18.4      SDL_bool freesrc;
    18.5      SDL_AudioSpec spec;
    18.6      int volume;
    18.7 +    int play_count;
    18.8      Sint64 start;
    18.9      Sint64 stop;
   18.10 -    SDL_AudioCVT cvt;
   18.11 +    Uint8 *buffer;
   18.12 +    SDL_AudioStream *stream;
   18.13      int numloops;
   18.14      WAVLoopPoint *loops;
   18.15 -} WAVStream;
   18.16 +} WAV_Music;
   18.17  
   18.18  /*
   18.19      Taken with permission from SDL_wave.h, part of the SDL library,
   18.20 @@ -116,84 +118,107 @@
   18.21  
   18.22  
   18.23  /* Function to load the WAV/AIFF stream */
   18.24 -static SDL_bool LoadWAVStream(WAVStream *wave);
   18.25 -static SDL_bool LoadAIFFStream(WAVStream *wave);
   18.26 +static SDL_bool LoadWAVMusic(WAV_Music *wave);
   18.27 +static SDL_bool LoadAIFFMusic(WAV_Music *wave);
   18.28  
   18.29 +static void WAV_Delete(void *context);
   18.30  
   18.31  /* Load a WAV stream from the given RWops object */
   18.32 -static void *WAVStream_CreateFromRW(SDL_RWops *src, int freesrc)
   18.33 +static void *WAV_CreateFromRW(SDL_RWops *src, int freesrc)
   18.34  {
   18.35 -    WAVStream *wave;
   18.36 +    WAV_Music *music;
   18.37 +    Uint32 magic;
   18.38      SDL_bool loaded = SDL_FALSE;
   18.39  
   18.40 -    wave = (WAVStream *)SDL_calloc(1, sizeof(*wave));
   18.41 -    if (wave) {
   18.42 -        Uint32 magic;
   18.43 +    music = (WAV_Music *)SDL_calloc(1, sizeof(*music));
   18.44 +    if (!music) {
   18.45 +        SDL_OutOfMemory();
   18.46 +        return NULL;
   18.47 +    }
   18.48 +    music->volume = MIX_MAX_VOLUME;
   18.49  
   18.50 -        wave->src = src;
   18.51 -        wave->freesrc = freesrc;
   18.52 +    magic = SDL_ReadLE32(src);
   18.53 +    if (magic == RIFF || magic == WAVE) {
   18.54 +        loaded = LoadWAVMusic(music);
   18.55 +    } else if (magic == FORM) {
   18.56 +        loaded = LoadAIFFMusic(music);
   18.57 +    } else {
   18.58 +        Mix_SetError("Unknown WAVE format");
   18.59 +    }
   18.60 +    if (!loaded) {
   18.61 +        SDL_free(music);
   18.62 +        return NULL;
   18.63 +    }
   18.64 +    music->buffer = (Uint8*)SDL_malloc(music->spec.size);
   18.65 +    if (!music->buffer) {
   18.66 +        WAV_Delete(music);
   18.67 +        return NULL;
   18.68 +    }
   18.69 +    music->stream = SDL_NewAudioStream(
   18.70 +        music->spec.format, music->spec.channels, music->spec.freq,
   18.71 +        music_spec.format, music_spec.channels, music_spec.freq);
   18.72 +    if (!music->stream) {
   18.73 +        WAV_Delete(music);
   18.74 +        return NULL;
   18.75 +    }
   18.76  
   18.77 -        magic = SDL_ReadLE32(src);
   18.78 -        if (magic == RIFF || magic == WAVE) {
   18.79 -            loaded = LoadWAVStream(wave);
   18.80 -        } else if (magic == FORM) {
   18.81 -            loaded = LoadAIFFStream(wave);
   18.82 -        } else {
   18.83 -            Mix_SetError("Unknown WAVE format");
   18.84 -        }
   18.85 -        if (!loaded) {
   18.86 -            SDL_free(wave);
   18.87 -            return(NULL);
   18.88 -        }
   18.89 -        SDL_BuildAudioCVT(&wave->cvt,
   18.90 -            wave->spec.format, wave->spec.channels, wave->spec.freq,
   18.91 -            music_spec.format, music_spec.channels, music_spec.freq);
   18.92 -        wave->volume = MIX_MAX_VOLUME;
   18.93 -    } else {
   18.94 -        SDL_OutOfMemory();
   18.95 -    }
   18.96 -    return wave;
   18.97 +    music->src = src;
   18.98 +    music->freesrc = freesrc;
   18.99 +    return music;
  18.100  }
  18.101  
  18.102 -static void WAVStream_SetVolume(void *context, int volume)
  18.103 +static void WAV_SetVolume(void *context, int volume)
  18.104  {
  18.105 -    WAVStream *wave = (WAVStream *)context;
  18.106 -    wave->volume = volume;
  18.107 +    WAV_Music *music = (WAV_Music *)context;
  18.108 +    music->volume = volume;
  18.109  }
  18.110  
  18.111  /* Start playback of a given WAV stream */
  18.112 -static int WAVStream_Play(void *context)
  18.113 +static int WAV_Play(void *context, int play_count)
  18.114  {
  18.115 -    WAVStream *wave = (WAVStream *)context;
  18.116 +    WAV_Music *music = (WAV_Music *)context;
  18.117      int i;
  18.118 -    for (i = 0; i < wave->numloops; ++i) {
  18.119 -        WAVLoopPoint *loop = &wave->loops[i];
  18.120 +    for (i = 0; i < music->numloops; ++i) {
  18.121 +        WAVLoopPoint *loop = &music->loops[i];
  18.122          loop->active = SDL_TRUE;
  18.123          loop->current_play_count = loop->initial_play_count;
  18.124      }
  18.125 -    SDL_RWseek(wave->src, wave->start, RW_SEEK_SET);
  18.126 -    return 0;
  18.127 +    music->play_count = play_count;
  18.128 +    return SDL_RWseek(music->src, music->start, RW_SEEK_SET);
  18.129  }
  18.130  
  18.131 -/* Play some of a stream previously started with WAVStream_Play() */
  18.132 -static int PlaySome(WAVStream *wave, Uint8 *stream, int len)
  18.133 +/* Play some of a stream previously started with WAV_Play() */
  18.134 +static int WAV_GetSome(void *context, void *data, int bytes, SDL_bool *done)
  18.135  {
  18.136 +    WAV_Music *music = (WAV_Music *)context;
  18.137      Sint64 pos, stop;
  18.138      WAVLoopPoint *loop;
  18.139      Sint64 loop_start;
  18.140      Sint64 loop_stop;
  18.141 +    SDL_bool looped = SDL_FALSE;
  18.142      int i;
  18.143 -    int consumed;
  18.144 +    int filled, amount, result;
  18.145  
  18.146 -    pos = SDL_RWtell(wave->src);
  18.147 -    stop = wave->stop;
  18.148 +    filled = SDL_AudioStreamGet(music->stream, data, bytes);
  18.149 +    if (filled != 0) {
  18.150 +        return filled;
  18.151 +    }
  18.152 +
  18.153 +    if (!music->play_count) {
  18.154 +        /* All done */
  18.155 +        *done = SDL_TRUE;
  18.156 +        return 0;
  18.157 +    }
  18.158 +
  18.159 +    pos = SDL_RWtell(music->src);
  18.160 +    stop = music->stop;
  18.161      loop = NULL;
  18.162 -    for (i = 0; i < wave->numloops; ++i) {
  18.163 -        loop = &wave->loops[i];
  18.164 +    for (i = 0; i < music->numloops; ++i) {
  18.165 +        loop = &music->loops[i];
  18.166          if (loop->active) {
  18.167 -            const int bytes_per_sample = (SDL_AUDIO_BITSIZE(wave->spec.format) / 8) * wave->spec.channels;
  18.168 -            loop_start = wave->start + loop->start * bytes_per_sample;
  18.169 -            loop_stop = wave->start + (loop->stop + 1) * bytes_per_sample;
  18.170 +            const int bytes_per_sample = (SDL_AUDIO_BITSIZE(music->spec.format) / 8) * music->spec.channels;
  18.171 +            loop_start = music->start + loop->start * bytes_per_sample;
  18.172 +            loop_stop = music->start + (loop->stop + 1) * bytes_per_sample;
  18.173              if (pos >= loop_start && pos < loop_stop)
  18.174              {
  18.175                  stop = loop_stop;
  18.176 @@ -203,97 +228,79 @@
  18.177          loop = NULL;
  18.178      }
  18.179  
  18.180 -    if (wave->cvt.needed) {
  18.181 -        int original_len = (int)((double)len/wave->cvt.len_ratio); 
  18.182 -        /* Make sure the length is a multiple of the sample size */
  18.183 -        {
  18.184 -            const int bytes_per_sample = (SDL_AUDIO_BITSIZE(wave->spec.format) / 8) * wave->spec.channels;
  18.185 -            const int alignment_mask = (bytes_per_sample - 1);
  18.186 -            original_len &= ~alignment_mask;
  18.187 +    amount = music->spec.size;
  18.188 +    if ((stop - pos) < amount) {
  18.189 +        amount = (int)(stop - pos);
  18.190 +    }
  18.191 +    amount = (int)SDL_RWread(music->src, music->buffer, 1, amount);
  18.192 +    if (amount > 0) {
  18.193 +        result = SDL_AudioStreamPut(music->stream, music->buffer, amount);
  18.194 +        if (result < 0) {
  18.195 +            return -1;
  18.196          }
  18.197 -        if (wave->cvt.len != original_len) {
  18.198 -            int worksize;
  18.199 -            if (wave->cvt.buf != NULL) {
  18.200 -                SDL_free(wave->cvt.buf);
  18.201 -            }
  18.202 -            worksize = original_len*wave->cvt.len_mult;
  18.203 -            wave->cvt.buf=(Uint8 *)SDL_malloc(worksize);
  18.204 -            if (wave->cvt.buf == NULL) {
  18.205 -                return 0;
  18.206 -            }
  18.207 -            wave->cvt.len = original_len;
  18.208 -        }
  18.209 -        if ((stop - pos) < original_len) {
  18.210 -            original_len = (int)(stop - pos);
  18.211 -        }
  18.212 -        original_len = (int)SDL_RWread(wave->src, wave->cvt.buf, 1, original_len);
  18.213 -        wave->cvt.len = original_len;
  18.214 -        SDL_ConvertAudio(&wave->cvt);
  18.215 -        SDL_MixAudioFormat(stream, wave->cvt.buf, music_spec.format, wave->cvt.len_cvt, wave->volume);
  18.216 -        consumed = wave->cvt.len_cvt;
  18.217      } else {
  18.218 -        Uint8 *data;
  18.219 -        if ((stop - pos) < len) {
  18.220 -            len = (int)(stop - pos);
  18.221 -        }
  18.222 -        data = SDL_stack_alloc(Uint8, len);
  18.223 -        if (data) {
  18.224 -            len = (int)SDL_RWread(wave->src, data, 1, len);
  18.225 -            SDL_MixAudioFormat(stream, data, music_spec.format, len, wave->volume);
  18.226 -            SDL_stack_free(data);
  18.227 -        }
  18.228 -        consumed = len;
  18.229 +        /* We might be looping, continue */
  18.230      }
  18.231  
  18.232 -    if (loop && SDL_RWtell(wave->src) >= stop) {
  18.233 +    if (loop && SDL_RWtell(music->src) >= stop) {
  18.234          if (loop->current_play_count == 1) {
  18.235              loop->active = SDL_FALSE;
  18.236          } else {
  18.237              if (loop->current_play_count > 0) {
  18.238                  --loop->current_play_count;
  18.239              }
  18.240 -            SDL_RWseek(wave->src, loop_start, RW_SEEK_SET);
  18.241 +            SDL_RWseek(music->src, loop_start, RW_SEEK_SET);
  18.242 +            looped = SDL_TRUE;
  18.243          }
  18.244      }
  18.245 -    return consumed;
  18.246 +
  18.247 +    if (!looped && SDL_RWtell(music->src) >= music->stop) {
  18.248 +        if (music->play_count == 1) {
  18.249 +            music->play_count = 0;
  18.250 +            SDL_AudioStreamFlush(music->stream);
  18.251 +        } else {
  18.252 +            int play_count = -1;
  18.253 +            if (music->play_count > 0) {
  18.254 +                play_count = (music->play_count - 1);
  18.255 +            }
  18.256 +            if (WAV_Play(music, play_count) < 0) {
  18.257 +                return -1;
  18.258 +            }
  18.259 +        }
  18.260 +    }
  18.261 +
  18.262 +    /* We'll get called again in the case where we looped or have more data */
  18.263 +    return 0;
  18.264  }
  18.265  
  18.266 -static int WAVStream_GetAudio(void *context, void *data, int bytes)
  18.267 +static int WAV_GetAudio(void *context, void *data, int bytes)
  18.268  {
  18.269 -    WAVStream *wave = (WAVStream *)context;
  18.270 -    Uint8 *stream = (Uint8 *)data;
  18.271 -    int len = bytes;
  18.272 -
  18.273 -    while ((SDL_RWtell(wave->src) < wave->stop) && (len > 0)) {
  18.274 -        int consumed = PlaySome(wave, stream, len);
  18.275 -        if (!consumed)
  18.276 -            break;
  18.277 -
  18.278 -        stream += consumed;
  18.279 -        len -= consumed;
  18.280 -    }
  18.281 -    return len;
  18.282 +    WAV_Music *music = (WAV_Music *)context;
  18.283 +    return music_pcm_getaudio(context, data, bytes, music->volume, WAV_GetSome);
  18.284  }
  18.285  
  18.286  /* Close the given WAV stream */
  18.287 -static void WAVStream_Delete(void *context)
  18.288 +static void WAV_Delete(void *context)
  18.289  {
  18.290 -    WAVStream *wave = (WAVStream *)context;
  18.291 +    WAV_Music *music = (WAV_Music *)context;
  18.292  
  18.293      /* Clean up associated data */
  18.294 -    if (wave->loops) {
  18.295 -        SDL_free(wave->loops);
  18.296 +    if (music->loops) {
  18.297 +        SDL_free(music->loops);
  18.298      }
  18.299 -    if (wave->cvt.buf) {
  18.300 -        SDL_free(wave->cvt.buf);
  18.301 +    if (music->stream) {
  18.302 +        SDL_FreeAudioStream(music->stream);
  18.303      }
  18.304 -    if (wave->freesrc) {
  18.305 -        SDL_RWclose(wave->src);
  18.306 +    if (music->buffer) {
  18.307 +        SDL_free(music->buffer);
  18.308      }
  18.309 -    SDL_free(wave);
  18.310 +    if (music->freesrc) {
  18.311 +        SDL_RWclose(music->src);
  18.312 +    }
  18.313 +    SDL_free(music);
  18.314  }
  18.315  
  18.316 -static SDL_bool ParseFMT(WAVStream *wave, Uint32 chunk_length)
  18.317 +static SDL_bool ParseFMT(WAV_Music *wave, Uint32 chunk_length)
  18.318  {
  18.319      SDL_AudioSpec *spec = &wave->spec;
  18.320      WaveFMT *format;
  18.321 @@ -339,6 +346,10 @@
  18.322      }
  18.323      spec->channels = (Uint8) SDL_SwapLE16(format->channels);
  18.324      spec->samples = 4096;       /* Good default buffer size */
  18.325 +    /* SDL_CalculateAudioSpec */
  18.326 +    spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8;
  18.327 +    spec->size *= spec->channels;
  18.328 +    spec->size *= spec->samples;
  18.329  
  18.330      loaded = SDL_TRUE;
  18.331  
  18.332 @@ -347,7 +358,7 @@
  18.333      return loaded;
  18.334  }
  18.335  
  18.336 -static SDL_bool ParseDATA(WAVStream *wave, Uint32 chunk_length)
  18.337 +static SDL_bool ParseDATA(WAV_Music *wave, Uint32 chunk_length)
  18.338  {
  18.339      wave->start = SDL_RWtell(wave->src);
  18.340      wave->stop = wave->start + chunk_length;
  18.341 @@ -355,7 +366,7 @@
  18.342      return SDL_TRUE;
  18.343  }
  18.344  
  18.345 -static SDL_bool AddLoopPoint(WAVStream *wave, Uint32 play_count, Uint32 start, Uint32 stop)
  18.346 +static SDL_bool AddLoopPoint(WAV_Music *wave, Uint32 play_count, Uint32 start, Uint32 stop)
  18.347  {
  18.348      WAVLoopPoint *loop;
  18.349      WAVLoopPoint *loops = SDL_realloc(wave->loops, (wave->numloops + 1)*sizeof(*wave->loops));
  18.350 @@ -375,7 +386,7 @@
  18.351      return SDL_TRUE;
  18.352  }
  18.353  
  18.354 -static SDL_bool ParseSMPL(WAVStream *wave, Uint32 chunk_length)
  18.355 +static SDL_bool ParseSMPL(WAV_Music *wave, Uint32 chunk_length)
  18.356  {
  18.357      SamplerChunk *chunk;
  18.358      Uint8 *data;
  18.359 @@ -406,7 +417,7 @@
  18.360      return loaded;
  18.361  }
  18.362  
  18.363 -static SDL_bool LoadWAVStream(WAVStream *wave)
  18.364 +static SDL_bool LoadWAVMusic(WAV_Music *wave)
  18.365  {
  18.366      SDL_RWops *src = wave->src;
  18.367      Uint32 chunk_type;
  18.368 @@ -491,7 +502,7 @@
  18.369              (sanebuf[5] >> 1)) >> (29 - sanebuf[1]);
  18.370  }
  18.371  
  18.372 -static SDL_bool LoadAIFFStream(WAVStream *wave)
  18.373 +static SDL_bool LoadAIFFMusic(WAV_Music *wave)
  18.374  {
  18.375      SDL_RWops *src = wave->src;
  18.376      SDL_AudioSpec *spec = &wave->spec;
  18.377 @@ -604,17 +615,17 @@
  18.378  
  18.379      NULL,   /* Load */
  18.380      NULL,   /* Open */
  18.381 -    WAVStream_CreateFromRW,
  18.382 +    WAV_CreateFromRW,
  18.383      NULL,   /* CreateFromFile */
  18.384 -    WAVStream_SetVolume,
  18.385 -    WAVStream_Play,
  18.386 +    WAV_SetVolume,
  18.387 +    WAV_Play,
  18.388      NULL,   /* IsPlaying */
  18.389 -    WAVStream_GetAudio,
  18.390 +    WAV_GetAudio,
  18.391      NULL,   /* Seek */
  18.392      NULL,   /* Pause */
  18.393      NULL,   /* Resume */
  18.394      NULL,   /* Stop */
  18.395 -    WAVStream_Delete,
  18.396 +    WAV_Delete,
  18.397      NULL,   /* Close */
  18.398      NULL,   /* Unload */
  18.399  };