From 84476f6e7418fa0f55a3d5d515eebf74897cd128 Mon Sep 17 00:00:00 2001
From: Ozkan Sezer <[EMAIL REDACTED]>
Date: Wed, 11 Oct 2023 10:51:02 +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...
Set the SDL2MIXER_WAVPACK_DSD cmake option to enable it.
---
CMakeLists.txt | 4 ++++
src/codecs/music_wavpack.c | 34 ++++++++++++++++++++++++++--------
2 files changed, 30 insertions(+), 8 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0458c13d..287a9794 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -190,6 +190,7 @@ cmake_dependent_option(SDL3MIXER_VORBIS_VORBISFILE_SHARED "Dynamically load vorb
option(SDL3MIXER_WAVE "Enable streaming WAVE music" ON)
option(SDL3MIXER_WAVPACK "Enable WavPack music" ON)
+cmake_dependent_option(SDL3MIXER_WAVPACK_DSD "Enable WavPack DSD music support" OFF SDL3MIXER_WAVPACK OFF)
cmake_dependent_option(SDL3MIXER_WAVPACK_SHARED "Dynamically load WavPack library" "${SDL3MIXER_DEPS_SHARED}" SDL3MIXER_WAVPACK OFF)
if(SDL3MIXER_VORBIS_TREMOR OR SDL3MIXER_VORBIS_VORBISFILE OR SDL3MIXER_FLAC_LIBFLAC OR SDL3MIXER_OPUS)
@@ -1061,6 +1062,9 @@ if(SDL3MIXER_WAVPACK)
endif()
if(SDL3MIXER_WAVPACK_ENABLED)
target_compile_definitions(${sdl3_mixer_target_name} PRIVATE MUSIC_WAVPACK)
+ if(SDL3MIXER_WAVPACK_DSD)
+ target_compile_definitions(${sdl3_mixer_target_name} PRIVATE MUSIC_WAVPACK_DSD)
+ endif()
if(SDL3MIXER_WAVPACK_SHARED)
target_include_directories(${sdl3_mixer_target_name} PRIVATE
$<TARGET_PROPERTY:WavPack::WavPack,INCLUDE_DIRECTORIES>
diff --git a/src/codecs/music_wavpack.c b/src/codecs/music_wavpack.c
index 78f16b65..5bb465f5 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, SDL_bool freesrc, SDL_bool *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, SDL_bool freesrc)
{
@@ -356,7 +366,7 @@ static void *WAVPACK_CreateFromRW_internal(SDL_RWops *src1, SDL_RWops *src2, SDL
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);
@@ -374,12 +384,13 @@ static void *WAVPACK_CreateFromRW_internal(SDL_RWops *src1, SDL_RWops *src2, SDL
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 = SDL_FALSE; /* 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) {
@@ -391,6 +402,7 @@ static void *WAVPACK_CreateFromRW_internal(SDL_RWops *src1, SDL_RWops *src2, SDL
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",
@@ -411,10 +423,9 @@ static void *WAVPACK_CreateFromRW_internal(SDL_RWops *src1, SDL_RWops *src2, SDL
break;
}
-
srcspec.format = format;
srcspec.channels = music->channels;
- srcspec.freq = (int)music->samplerate / music->decimation;
+ srcspec.freq = (int)music->samplerate / DECIMATION(music);
music->stream = SDL_CreateAudioStream(&srcspec, &music_spec);
if (!music->stream) {
WAVPACK_Delete(music);
@@ -422,7 +433,7 @@ static void *WAVPACK_CreateFromRW_internal(SDL_RWops *src1, SDL_RWops *src2, SDL
}
music->frames = 4096/*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);
@@ -509,11 +520,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;
@@ -578,9 +590,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;
}
@@ -610,7 +624,9 @@ static void WAVPACK_Delete(void *context)
SDL_DestroyAudioStream(music->stream);
}
SDL_free(music->buffer);
+ #ifdef MUSIC_WAVPACK_DSD
SDL_free(music->decimation_ctx);
+ #endif
if (music->src2) {
SDL_RWclose(music->src2);
}
@@ -620,6 +636,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 */
@@ -707,6 +724,7 @@ static void decimation_reset(void *context)
sp[i].ratio = ratio;
}
}
+#endif /* MUSIC_WAVPACK_DSD */
Mix_MusicInterface Mix_MusicInterface_WAVPACK =
{