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 =
{