SDL_mixer: music_wavpack.c: disable DSD music decoding by default.

From 81ba75b882543fbfe27e5ce88c5ab8e23b74ec0b Mon Sep 17 00:00:00 2001
From: Ozkan Sezer <[EMAIL REDACTED]>
Date: Wed, 11 Oct 2023 10:51:40 +0300
Subject: [PATCH] music_wavpack.c: disable DSD music decoding by default.

DSD files aren't of common interest. And the decimation
code isn't easy on the cpu, either...

Use the --enable-music-wavpack-dsd configury switch, or
set the SDL2MIXER_WAVPACK_DSD cmake option to enable it.
---
 CMakeLists.txt             |  4 +++
 Makefile.os2               |  5 ++++
 configure                  | 54 ++++++++++++++++++++++++--------------
 configure.ac               |  6 +++++
 src/codecs/music_wavpack.c | 33 ++++++++++++++++++-----
 5 files changed, 75 insertions(+), 27 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 41f32406..3f0761fd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -181,6 +181,7 @@ cmake_dependent_option(SDL2MIXER_VORBIS_VORBISFILE_SHARED "Dynamically load vorb
 option(SDL2MIXER_WAVE "Enable streaming WAVE music" ON)
 
 option(SDL2MIXER_WAVPACK "Enable WavPack music" ON)
+cmake_dependent_option(SDL2MIXER_WAVPACK_DSD "Enable WavPack DSD music support" OFF SDL2MIXER_WAVPACK OFF)
 cmake_dependent_option(SDL2MIXER_WAVPACK_SHARED "Dynamically load WavPack library" "${SDL2MIXER_DEPS_SHARED}" SDL2MIXER_WAVPACK OFF)
 
 if(SDL2MIXER_VORBIS_TREMOR OR SDL2MIXER_VORBIS_VORBISFILE OR SDL2MIXER_FLAC_LIBFLAC OR SDL2MIXER_OPUS)
@@ -861,6 +862,9 @@ if(SDL2MIXER_WAVPACK)
             list(APPEND PC_REQUIRES wavpack)
         endif()
     endif()
+    if(SDL2MIXER_WAVPACK_DSD)
+        target_compile_definitions(SDL2_mixer PRIVATE MUSIC_WAVPACK_DSD)
+    endif()
     if(SDL2MIXER_WAVPACK_SHARED)
         target_include_directories(SDL2_mixer PRIVATE
             $<TARGET_PROPERTY:WavPack::WavPack,INCLUDE_DIRECTORIES>
diff --git a/Makefile.os2 b/Makefile.os2
index ee158a05..8b5bec29 100644
--- a/Makefile.os2
+++ b/Makefile.os2
@@ -37,6 +37,8 @@ USE_MPG123=yes
 USE_DRMP3=no
 # wavpack music support
 USE_WAVPACK=yes
+# wavpack DSD music support
+USE_WAVPACK_DSD= no
 # midi music support (using timidity)
 USE_TIMIDITY=yes
 # midi music support (using fluidsynth)
@@ -124,6 +126,9 @@ CFLAGS+= -DMUSIC_FLAC_DRFLAC
 
 !ifeq USE_WAVPACK yes
 CFLAGS+= -DMUSIC_WAVPACK
+!ifeq USE_WAVPACK_DSD yes
+CFLAGS+= -DMUSIC_WAVPACK_DSD
+!endif
 LIBS+= wavpack.lib
 !endif
 
diff --git a/configure b/configure
index 6538a7ec..845f90fb 100755
--- a/configure
+++ b/configure
@@ -1004,6 +1004,7 @@ enable_music_opus
 enable_music_opus_shared
 enable_music_wavpack
 enable_music_wavpack_shared
+enable_music_wavpack_dsd
 '
       ac_precious_vars='build_alias
 host_alias
@@ -1726,6 +1727,8 @@ Optional Features:
   --enable-music-wavpack  enable WavPack music [default=yes]
   --enable-music-wavpack-shared
                           dynamically load WavPack library [default=yes]
+  --enable-music-wavpack-dsd
+                          enable WavPack DSD music support [default=no]
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
@@ -4962,13 +4965,13 @@ then :
 else $as_nop
   lt_cv_nm_interface="BSD nm"
   echo "int some_variable = 0;" > conftest.$ac_ext
-  (eval echo "\"\$as_me:4965: $ac_compile\"" >&5)
+  (eval echo "\"\$as_me:4968: $ac_compile\"" >&5)
   (eval "$ac_compile" 2>conftest.err)
   cat conftest.err >&5
-  (eval echo "\"\$as_me:4968: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+  (eval echo "\"\$as_me:4971: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
   (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
   cat conftest.err >&5
-  (eval echo "\"\$as_me:4971: output\"" >&5)
+  (eval echo "\"\$as_me:4974: output\"" >&5)
   cat conftest.out >&5
   if $GREP 'External.*some_variable' conftest.out > /dev/null; then
     lt_cv_nm_interface="MS dumpbin"
@@ -6227,7 +6230,7 @@ ia64-*-hpux*)
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 6230 "configure"' > conftest.$ac_ext
+  echo '#line 6233 "configure"' > conftest.$ac_ext
   if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -7900,11 +7903,11 @@ else $as_nop
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:7903: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:7906: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:7907: \$? = $ac_status" >&5
+   echo "$as_me:7910: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -8250,11 +8253,11 @@ else $as_nop
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8253: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8256: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:8257: \$? = $ac_status" >&5
+   echo "$as_me:8260: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -8357,11 +8360,11 @@ else $as_nop
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8360: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8363: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:8364: \$? = $ac_status" >&5
+   echo "$as_me:8367: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -8413,11 +8416,11 @@ else $as_nop
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8416: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8419: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:8420: \$? = $ac_status" >&5
+   echo "$as_me:8423: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -10856,7 +10859,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 10859 "configure"
+#line 10862 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -10953,7 +10956,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 10956 "configure"
+#line 10959 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -14652,11 +14655,11 @@ else $as_nop
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:14655: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:14658: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:14659: \$? = $ac_status" >&5
+   echo "$as_me:14662: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -14753,11 +14756,11 @@ else $as_nop
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:14756: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:14759: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:14760: \$? = $ac_status" >&5
+   echo "$as_me:14763: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -14806,11 +14809,11 @@ else $as_nop
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:14809: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:14812: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:14813: \$? = $ac_status" >&5
+   echo "$as_me:14816: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -19321,6 +19324,14 @@ else $as_nop
   enable_music_wavpack_shared=yes
 fi
 
+# Check whether --enable-music-wavpack-dsd was given.
+if test ${enable_music_wavpack_dsd+y}
+then :
+  enableval=$enable_music_wavpack_dsd;
+else $as_nop
+  enable_music_wavpack_dsd=no
+fi
+
 if test x$enable_music_wavpack = xyes; then
     LIBS_SAVED="$LIBS"
 
@@ -19534,6 +19545,9 @@ fi
                 ;;
         esac
         EXTRA_CFLAGS="$EXTRA_CFLAGS -DMUSIC_WAVPACK $WAVPACK_CFLAGS"
+        if test x$enable_music_wavpack_dsd = xyes; then
+            EXTRA_CFLAGS="$EXTRA_CFLAGS -DMUSIC_WAVPACK_DSD"
+        fi
         if test x$have_wavpack_hdr2 = xyes; then
             EXTRA_CFLAGS="$EXTRA_CFLAGS -DHAVE_WAVPACK_H"
         fi
diff --git a/configure.ac b/configure.ac
index 863af93b..8620e33d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -960,6 +960,9 @@ AC_ARG_ENABLE([music-wavpack],
 AC_ARG_ENABLE([music-wavpack-shared],
 [AS_HELP_STRING([--enable-music-wavpack-shared], [dynamically load WavPack library [default=yes]])],
               [], [enable_music_wavpack_shared=yes])
+AC_ARG_ENABLE([music-wavpack-dsd],
+[AS_HELP_STRING([--enable-music-wavpack-dsd], [enable WavPack DSD music support [default=no]])],
+                [], [enable_music_wavpack_dsd=no])
 if test x$enable_music_wavpack = xyes; then
     LIBS_SAVED="$LIBS"
     PKG_CHECK_MODULES([WAVPACK], [wavpack >= 4.0], [dnl
@@ -999,6 +1002,9 @@ if test x$enable_music_wavpack = xyes; then
                 ;;
         esac
         EXTRA_CFLAGS="$EXTRA_CFLAGS -DMUSIC_WAVPACK $WAVPACK_CFLAGS"
+        if test x$enable_music_wavpack_dsd = xyes; then
+            EXTRA_CFLAGS="$EXTRA_CFLAGS -DMUSIC_WAVPACK_DSD"
+        fi
         if test x$have_wavpack_hdr2 = xyes; then
             EXTRA_CFLAGS="$EXTRA_CFLAGS -DHAVE_WAVPACK_H"
         fi
diff --git a/src/codecs/music_wavpack.c b/src/codecs/music_wavpack.c
index b6dea9af..15876365 100644
--- a/src/codecs/music_wavpack.c
+++ b/src/codecs/music_wavpack.c
@@ -185,8 +185,11 @@ typedef struct {
     WavpackContext *ctx;
     int64_t numsamples;
     uint32_t samplerate;
-    int bps, channels, mode, decimation;
+    int bps, channels, mode;
+    #ifdef MUSIC_WAVPACK_DSD
+    int decimation;
     void *decimation_ctx;
+    #endif
 
     SDL_AudioStream *stream;
     void *buffer;
@@ -287,9 +290,16 @@ static int WAVPACK_Seek(void *context, double time);
 static void WAVPACK_Delete(void *context);
 static void *WAVPACK_CreateFromRW_internal(SDL_RWops *src1, SDL_RWops *src2, int freesrc, int *freesrc2);
 
+#ifdef MUSIC_WAVPACK_DSD
 static void *decimation_init(int num_channels, int ratio);
 static int decimation_run(void *context, int32_t *samples, int num_samples);
 static void decimation_reset(void *context);
+#define FLAGS_DSD OPEN_DSD_AS_PCM
+#define DECIMATION(x) (x)->decimation
+#else
+#define FLAGS_DSD 0
+#define DECIMATION(x) 1
+#endif
 
 static void *WAVPACK_CreateFromRW(SDL_RWops *src, int freesrc)
 {
@@ -355,7 +365,7 @@ static void *WAVPACK_CreateFromRW_internal(SDL_RWops *src1, SDL_RWops *src2, int
     music->volume = MIX_MAX_VOLUME;
 
     music->ctx = (wvpk.WavpackOpenFileInputEx64 != NULL) ?
-                  wvpk.WavpackOpenFileInputEx64(&sdl_reader64, src1, src2, err, OPEN_NORMALIZE|OPEN_TAGS|OPEN_DSD_AS_PCM, 0) :
+                  wvpk.WavpackOpenFileInputEx64(&sdl_reader64, src1, src2, err, OPEN_NORMALIZE|OPEN_TAGS|FLAGS_DSD, 0) :
                   wvpk.WavpackOpenFileInputEx(&sdl_reader32, src1, src2, err, OPEN_NORMALIZE|OPEN_TAGS, 0);
     if (!music->ctx) {
         Mix_SetError("%s", err);
@@ -373,12 +383,13 @@ static void *WAVPACK_CreateFromRW_internal(SDL_RWops *src1, SDL_RWops *src2, int
     music->bps = wvpk.WavpackGetBytesPerSample(music->ctx) << 3;
     music->channels = wvpk.WavpackGetNumChannels(music->ctx);
     music->mode = wvpk.WavpackGetMode(music->ctx);
-    music->decimation = 1;
 
     if (freesrc2) {
        *freesrc2 = 0; /* WAVPACK_Delete() will free it. */
     }
 
+    #ifdef MUSIC_WAVPACK_DSD
+    music->decimation = 1;
     /* for very high sample rates (including DSD, which will normally be 352,800 Hz)
      * decimate 4x here before sending on */
     if (music->samplerate >= 256000) {
@@ -390,6 +401,7 @@ static void *WAVPACK_CreateFromRW_internal(SDL_RWops *src1, SDL_RWops *src2, int
             return NULL;
         }
     }
+    #endif
 
     #if WAVPACK_DBG
     SDL_Log("WavPack loader:\n numsamples: %" SDL_PRIs64 "\n samplerate: %d\n bitspersample: %d\n channels: %d\n mode: 0x%x\n lossy: %d\n duration: %f\n",
@@ -409,7 +421,7 @@ static void *WAVPACK_CreateFromRW_internal(SDL_RWops *src1, SDL_RWops *src2, int
         format = (music->mode & MODE_FLOAT) ? AUDIO_F32SYS : AUDIO_S32SYS;
         break;
     }
-    music->stream = SDL_NewAudioStream(format, (Uint8)music->channels, (int)music->samplerate / music->decimation,
+    music->stream = SDL_NewAudioStream(format, (Uint8)music->channels, (int)music->samplerate / DECIMATION(music),
                                        music_spec.format, music_spec.channels, music_spec.freq);
     if (!music->stream) {
         WAVPACK_Delete(music);
@@ -417,7 +429,7 @@ static void *WAVPACK_CreateFromRW_internal(SDL_RWops *src1, SDL_RWops *src2, int
     }
 
     music->frames = music_spec.samples;
-    music->buffer = SDL_malloc(music->frames * music->channels * sizeof(int32_t) * music->decimation);
+    music->buffer = SDL_malloc(music->frames * music->channels * sizeof(int32_t) * DECIMATION(music));
     if (!music->buffer) {
         SDL_OutOfMemory();
         WAVPACK_Delete(music);
@@ -504,11 +516,12 @@ static int WAVPACK_GetSome(void *context, void *data, int bytes, SDL_bool *done)
         return 0;
     }
 
-    amount = (int) wvpk.WavpackUnpackSamples(music->ctx, music->buffer, music->frames * music->decimation);
-
+    amount = (int) wvpk.WavpackUnpackSamples(music->ctx, music->buffer, music->frames * DECIMATION(music));
+    #ifdef MUSIC_WAVPACK_DSD
     if (amount && music->decimation_ctx) {
         amount = decimation_run(music->decimation_ctx, music->buffer, amount);
     }
+    #endif
 
     if (amount) {
         int32_t *src = (int32_t *)music->buffer;
@@ -573,9 +586,11 @@ static int WAVPACK_Seek(void *context, double time)
     if (!success) {
         return Mix_SetError("%s", wvpk.WavpackGetErrorMessage(music->ctx));
     }
+    #ifdef MUSIC_WAVPACK_DSD
     if (music->decimation_ctx) {
         decimation_reset(music->decimation_ctx);
     }
+    #endif
     return 0;
 }
 
@@ -605,7 +620,9 @@ static void WAVPACK_Delete(void *context)
         SDL_FreeAudioStream(music->stream);
     }
     SDL_free(music->buffer);
+    #ifdef MUSIC_WAVPACK_DSD
     SDL_free(music->decimation_ctx);
+    #endif
     if (music->src2) {
         SDL_RWclose(music->src2);
     }
@@ -615,6 +632,7 @@ static void WAVPACK_Delete(void *context)
     SDL_free(music);
 }
 
+#ifdef MUSIC_WAVPACK_DSD
 /* Decimation code for playing DSD (which comes from the library already decimated 8x) */
 /* Code provided by David Bryant. */
 /* sinc low-pass filter, cutoff = fs/12, 80 terms */
@@ -702,6 +720,7 @@ static void decimation_reset(void *context)
         sp[i].ratio = ratio;
     }
 }
+#endif /* MUSIC_WAVPACK_DSD */
 
 Mix_MusicInterface Mix_MusicInterface_WAVPACK =
 {