SDL_mixer: Use dr_mp3 instead of minimp3 for default MP3 support

From c94f6cec7269fb2d37b83791130a7f8f8109357d Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Fri, 20 May 2022 20:55:54 -0700
Subject: [PATCH] Use dr_mp3 instead of minimp3 for default MP3 support

---
 Android.mk                                    |    8 +-
 CHANGES.txt                                   |    4 +-
 Xcode/SDL_mixer.xcodeproj/project.pbxproj     |   28 +-
 configure                                     |   20 +-
 configure.ac                                  |   12 +-
 src/codecs/dr_mp3.h                           | 4785 +++++++++++++++++
 src/codecs/minimp3/LICENSE                    |  117 -
 src/codecs/minimp3/README.md                  |  310 --
 src/codecs/minimp3/minimp3.h                  | 1865 -------
 src/codecs/minimp3/minimp3_ex.h               | 1397 -----
 src/codecs/mp3utils.h                         |    2 +-
 src/codecs/{music_minimp3.c => music_drmp3.c} |  177 +-
 src/codecs/{music_minimp3.h => music_drmp3.h} |    4 +-
 src/music.c                                   |    6 +-
 src/music.h                                   |    2 +-
 15 files changed, 4916 insertions(+), 3821 deletions(-)
 create mode 100644 src/codecs/dr_mp3.h
 delete mode 100644 src/codecs/minimp3/LICENSE
 delete mode 100644 src/codecs/minimp3/README.md
 delete mode 100644 src/codecs/minimp3/minimp3.h
 delete mode 100644 src/codecs/minimp3/minimp3_ex.h
 rename src/codecs/{music_minimp3.c => music_drmp3.c} (50%)
 rename src/codecs/{music_minimp3.h => music_drmp3.h} (90%)

diff --git a/Android.mk b/Android.mk
index b1342f98..990e9d70 100644
--- a/Android.mk
+++ b/Android.mk
@@ -13,8 +13,8 @@ SUPPORT_OGG ?= false
 OGG_LIBRARY_PATH := external/ogg
 VORBIS_LIBRARY_PATH := external/tremor
 
-# Enable this if you want to support loading MP3 music via MINIMP3
-SUPPORT_MP3_MINIMP3 ?= true
+# Enable this if you want to support loading MP3 music via dr_mp3
+SUPPORT_MP3_DRMP3 ?= true
 
 # Enable this if you want to support loading MP3 music via MPG123
 SUPPORT_MP3_MPG123 ?= false
@@ -97,8 +97,8 @@ ifeq ($(SUPPORT_OGG),true)
     LOCAL_STATIC_LIBRARIES += ogg vorbisidec
 endif
 
-ifeq ($(SUPPORT_MP3_MINIMP3),true)
-    LOCAL_CFLAGS += -DMUSIC_MP3_MINIMP3
+ifeq ($(SUPPORT_MP3_DRMP3),true)
+    LOCAL_CFLAGS += -DMUSIC_MP3_DRMP3
 endif
 
 # This needs to be a shared library to comply with the LGPL license
diff --git a/CHANGES.txt b/CHANGES.txt
index 43aee3d8..d2b2b196 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,6 +1,6 @@
 2.0.5:
-Vitaly Novichkov - Fri May 20 14:45:53 PDT 2022
- * Added minimp3 codec library for MP3
+Sam Lantinga - Fri May 20 20:50:29 PDT 2022
+ * Added support for playing MP3 files using dr_mp3
 Mykola Rubets - Tue May 17 12:59:35 2022
  * Implemented a master volume feature, Mix_MasterVolume added to
    public api.
diff --git a/Xcode/SDL_mixer.xcodeproj/project.pbxproj b/Xcode/SDL_mixer.xcodeproj/project.pbxproj
index 65162864..0f30f9db 100644
--- a/Xcode/SDL_mixer.xcodeproj/project.pbxproj
+++ b/Xcode/SDL_mixer.xcodeproj/project.pbxproj
@@ -50,10 +50,10 @@
 		AAE406041F9607C300EDAF53 /* effect_stereoreverse.c in Sources */ = {isa = PBXBuildFile; fileRef = AAE405E01F9607C300EDAF53 /* effect_stereoreverse.c */; };
 		AAE406051F9607C300EDAF53 /* effects_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = AAE405E11F9607C300EDAF53 /* effects_internal.h */; };
 		BE1FA8CD07AF96B2004B6283 /* SDL_mixer.h in Headers */ = {isa = PBXBuildFile; fileRef = 1014BAEA010A4B677F000001 /* SDL_mixer.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		F37A8CCA2838404700C38E95 /* music_minimp3.h in Headers */ = {isa = PBXBuildFile; fileRef = F37A8CC82838404700C38E95 /* music_minimp3.h */; };
-		F37A8CCB2838404700C38E95 /* music_minimp3.h in Headers */ = {isa = PBXBuildFile; fileRef = F37A8CC82838404700C38E95 /* music_minimp3.h */; };
-		F37A8CCC2838404700C38E95 /* music_minimp3.c in Sources */ = {isa = PBXBuildFile; fileRef = F37A8CC92838404700C38E95 /* music_minimp3.c */; };
-		F37A8CCD2838404700C38E95 /* music_minimp3.c in Sources */ = {isa = PBXBuildFile; fileRef = F37A8CC92838404700C38E95 /* music_minimp3.c */; };
+		F37A8D2D2838924900C38E95 /* music_drmp3.h in Headers */ = {isa = PBXBuildFile; fileRef = F37A8D2B2838924900C38E95 /* music_drmp3.h */; };
+		F37A8D2E2838924900C38E95 /* music_drmp3.h in Headers */ = {isa = PBXBuildFile; fileRef = F37A8D2B2838924900C38E95 /* music_drmp3.h */; };
+		F37A8D2F2838924900C38E95 /* music_drmp3.c in Sources */ = {isa = PBXBuildFile; fileRef = F37A8D2C2838924900C38E95 /* music_drmp3.c */; };
+		F37A8D302838924900C38E95 /* music_drmp3.c in Sources */ = {isa = PBXBuildFile; fileRef = F37A8D2C2838924900C38E95 /* music_drmp3.c */; };
 		F3823337273195CC00F7F527 /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 639008C62385A822009019FA /* utils.c */; };
 		F3823338273195CF00F7F527 /* utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 639008C72385A822009019FA /* utils.h */; };
 		F3823339273195D200F7F527 /* effect_position.c in Sources */ = {isa = PBXBuildFile; fileRef = AAE405D01F9607C100EDAF53 /* effect_position.c */; };
@@ -194,8 +194,8 @@
 		BE1FA90607AF96B2004B6283 /* SDL2_mixer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDL2_mixer.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		BE1FA95407AF96B2004B6283 /* libSDL2_mixer.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSDL2_mixer.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		BE1FA95807AF96B3004B6283 /* Create DMG */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Create DMG"; sourceTree = BUILT_PRODUCTS_DIR; };
-		F37A8CC82838404700C38E95 /* music_minimp3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = music_minimp3.h; sourceTree = "<group>"; };
-		F37A8CC92838404700C38E95 /* music_minimp3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = music_minimp3.c; sourceTree = "<group>"; };
+		F37A8D2B2838924900C38E95 /* music_drmp3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = music_drmp3.h; sourceTree = "<group>"; };
+		F37A8D2C2838924900C38E95 /* music_drmp3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = music_drmp3.c; sourceTree = "<group>"; };
 		F3968B90281F817E00661875 /* opus.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = opus.xcodeproj; path = opus/opus.xcodeproj; sourceTree = "<group>"; };
 		F3968D71281FB5E100661875 /* config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = config.xcconfig; sourceTree = "<group>"; };
 		F3968D72281FB66200661875 /* tremor.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = tremor.xcodeproj; path = tremor/tremor.xcodeproj; sourceTree = "<group>"; };
@@ -301,6 +301,8 @@
 				639197F0239FE66700F1D8F8 /* mp3utils.h */,
 				AAE405DE1F9607C300EDAF53 /* music_cmd.c */,
 				AAE405DB1F9607C200EDAF53 /* music_cmd.h */,
+				F37A8D2C2838924900C38E95 /* music_drmp3.c */,
+				F37A8D2B2838924900C38E95 /* music_drmp3.h */,
 				AAE405D41F9607C100EDAF53 /* music_flac.c */,
 				AAE405C71F9607C000EDAF53 /* music_flac.h */,
 				AAE405C61F9607C000EDAF53 /* music_fluidsynth.c */,
@@ -309,8 +311,6 @@
 				AAE405DD1F9607C300EDAF53 /* music_mad.h */,
 				AAE405D81F9607C200EDAF53 /* music_mikmod.c */,
 				AAE405CF1F9607C100EDAF53 /* music_mikmod.h */,
-				F37A8CC92838404700C38E95 /* music_minimp3.c */,
-				F37A8CC82838404700C38E95 /* music_minimp3.h */,
 				AAE405C41F9607C000EDAF53 /* music_modplug.c */,
 				AAE405C51F9607C000EDAF53 /* music_modplug.h */,
 				AAE405DF1F9607C300EDAF53 /* music_mpg123.c */,
@@ -439,8 +439,8 @@
 				AAE405F61F9607C300EDAF53 /* load_aiff.h in Headers */,
 				AAE405E71F9607C300EDAF53 /* load_voc.h in Headers */,
 				AAE405EC1F9607C300EDAF53 /* music_wav.h in Headers */,
+				F37A8D2D2838924900C38E95 /* music_drmp3.h in Headers */,
 				AAE406011F9607C300EDAF53 /* music_mad.h in Headers */,
-				F37A8CCA2838404700C38E95 /* music_minimp3.h in Headers */,
 				AAE405E91F9607C300EDAF53 /* music_modplug.h in Headers */,
 				AAE405FE1F9607C300EDAF53 /* music_nativemidi.h in Headers */,
 				AAE405E41F9607C300EDAF53 /* mixer.h in Headers */,
@@ -477,12 +477,12 @@
 				F38233562731961C00F7F527 /* music_timidity.h in Headers */,
 				F38233542731961800F7F527 /* music_ogg.h in Headers */,
 				F382335C2731962B00F7F527 /* load_voc.h in Headers */,
-				F37A8CCB2838404700C38E95 /* music_minimp3.h in Headers */,
 				F382335D2731962D00F7F527 /* music_opus.h in Headers */,
 				F3823342273195E900F7F527 /* mp3utils.h in Headers */,
 				F38233602731963800F7F527 /* native_midi.h in Headers */,
 				F38233502731960F00F7F527 /* music_mpg123.h in Headers */,
 				F3823344273195EE00F7F527 /* music_cmd.h in Headers */,
+				F37A8D2E2838924900C38E95 /* music_drmp3.h in Headers */,
 				F38233582731962100F7F527 /* music_wav.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -695,6 +695,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				AAE405E21F9607C300EDAF53 /* load_aiff.c in Sources */,
+				F37A8D2F2838924900C38E95 /* music_drmp3.c in Sources */,
 				AAE405F01F9607C300EDAF53 /* load_voc.c in Sources */,
 				AAE405FC1F9607C300EDAF53 /* music_mikmod.c in Sources */,
 				AAE405EA1F9607C300EDAF53 /* music_fluidsynth.c in Sources */,
@@ -714,7 +715,6 @@
 				AAE405E51F9607C300EDAF53 /* mixer.c in Sources */,
 				0448E8AE108B937A00C9D3EA /* native_midi_macosx.c in Sources */,
 				630FBD8320D52105009867AB /* music_opus.c in Sources */,
-				F37A8CCC2838404700C38E95 /* music_minimp3.c in Sources */,
 				639008C82385A822009019FA /* utils.c in Sources */,
 				639197F1239FE66700F1D8F8 /* mp3utils.c in Sources */,
 			);
@@ -725,6 +725,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				F38233552731961A00F7F527 /* music_timidity.c in Sources */,
+				F37A8D302838924900C38E95 /* music_drmp3.c in Sources */,
 				F382334F2731960C00F7F527 /* music_mpg123.c in Sources */,
 				F382333B273195D800F7F527 /* effects_internal.c in Sources */,
 				0448E8AF108B937A00C9D3EA /* native_midi_macosx.c in Sources */,
@@ -744,7 +745,6 @@
 				F38233572731961F00F7F527 /* music_wav.c in Sources */,
 				F38233512731961100F7F527 /* music_nativemidi.c in Sources */,
 				F38233532731961600F7F527 /* music_ogg.c in Sources */,
-				F37A8CCD2838404700C38E95 /* music_minimp3.c in Sources */,
 				F3823337273195CC00F7F527 /* utils.c in Sources */,
 				F3823339273195D200F7F527 /* effect_position.c in Sources */,
 			);
@@ -845,7 +845,7 @@
 				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
 				GCC_NO_COMMON_BLOCKS = YES;
 				GCC_PREPROCESSOR_DEFINITIONS = (
-					MUSIC_MP3_MINIMP3,
+					MUSIC_MP3_DRMP3,
 					MUSIC_WAV,
 					"$(CONFIG_PREPROCESSOR_DEFINITIONS)",
 				);
@@ -892,7 +892,7 @@
 				GCC_NO_COMMON_BLOCKS = YES;
 				GCC_OPTIMIZATION_LEVEL = 0;
 				GCC_PREPROCESSOR_DEFINITIONS = (
-					MUSIC_MP3_MINIMP3,
+					MUSIC_MP3_DRMP3,
 					MUSIC_WAV,
 					"$(CONFIG_PREPROCESSOR_DEFINITIONS)",
 				);
diff --git a/configure b/configure
index b35f7daa..b5a95d1c 100755
--- a/configure
+++ b/configure
@@ -937,7 +937,7 @@ enable_music_ogg_shared
 enable_music_flac
 enable_music_flac_shared
 enable_music_mp3
-enable_music_mp3_minimp3
+enable_music_mp3_drmp3
 enable_music_mp3_mad_gpl
 enable_music_mp3_mad_gpl_dithering
 enable_music_mp3_mpg123
@@ -1632,8 +1632,8 @@ Optional Features:
   --enable-music-flac-shared
                           dynamically load FLAC library [default=yes]
   --enable-music-mp3      enable MP3 music [default=yes]
-  --enable-music-mp3-minimp3
-                          enable MP3 music via minimp3 [default=yes]
+  --enable-music-mp3-drmp3
+                          enable MP3 music via dr_mp3 [default=yes]
   --enable-music-mp3-mad-gpl
                           enable MP3 music via libmad GPL code [default=no]
   --enable-music-mp3-mad-gpl-dithering
@@ -17312,15 +17312,15 @@ else
 fi
 
 
-# Check whether --enable-music-mp3-minimp3 was given.
-if test "${enable_music_mp3_minimp3+set}" = set; then :
-  enableval=$enable_music_mp3_minimp3;
+# Check whether --enable-music-mp3-drmp3 was given.
+if test "${enable_music_mp3_drmp3+set}" = set; then :
+  enableval=$enable_music_mp3_drmp3;
 else
-  enable_music_mp3_minimp3=yes
+  enable_music_mp3_drmp3=yes
 fi
 
-if test x$enable_music_mp3_minimp3 = xyes; then
-    EXTRA_CFLAGS="$EXTRA_CFLAGS -DMUSIC_MP3_MINIMP3"
+if test x$enable_music_mp3_drmp3 = xyes; then
+    EXTRA_CFLAGS="$EXTRA_CFLAGS -DMUSIC_MP3_DRMP3"
 fi
 
 # Check whether --enable-music-mp3-mad-gpl was given.
@@ -17589,7 +17589,7 @@ $as_echo "$as_me: WARNING: mpg123 support disabled" >&2;}
     fi
 fi
 
-if test x$enable_music_mp3_minimp3 = xyes -o x$have_libmad = xyes -o x$have_libmpg123 = xyes; then
+if test x$enable_music_mp3_drmp3 = xyes -o x$have_libmad = xyes -o x$have_libmpg123 = xyes; then
     :
 else
     { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: MP3 support disabled" >&5
diff --git a/configure.ac b/configure.ac
index 63331a64..ee19d2ed 100644
--- a/configure.ac
+++ b/configure.ac
@@ -756,11 +756,11 @@ AC_ARG_ENABLE(music-mp3,
 [AS_HELP_STRING([--enable-music-mp3], [enable MP3 music [default=yes]])],
               [], enable_music_mp3=yes)
 
-AC_ARG_ENABLE(music-mp3-minimp3,
-[AS_HELP_STRING([--enable-music-mp3-minimp3], [enable MP3 music via minimp3 [default=yes]])],
-                  [], [enable_music_mp3_minimp3=yes])
-if test x$enable_music_mp3_minimp3 = xyes; then
-    EXTRA_CFLAGS="$EXTRA_CFLAGS -DMUSIC_MP3_MINIMP3"
+AC_ARG_ENABLE(music-mp3-drmp3,
+[AS_HELP_STRING([--enable-music-mp3-drmp3], [enable MP3 music via dr_mp3 [default=yes]])],
+                  [], [enable_music_mp3_drmp3=yes])
+if test x$enable_music_mp3_drmp3 = xyes; then
+    EXTRA_CFLAGS="$EXTRA_CFLAGS -DMUSIC_MP3_DRMP3"
 fi
 
 AC_ARG_ENABLE(music-mp3-mad-gpl,
@@ -835,7 +835,7 @@ if test x$enable_music_mp3_mpg123 = xyes; then
     fi
 fi
 
-if test x$enable_music_mp3_minimp3 = xyes -o x$have_libmad = xyes -o x$have_libmpg123 = xyes; then
+if test x$enable_music_mp3_drmp3 = xyes -o x$have_libmad = xyes -o x$have_libmpg123 = xyes; then
     :
 else
     AC_MSG_WARN([MP3 support disabled])
diff --git a/src/codecs/dr_mp3.h b/src/codecs/dr_mp3.h
new file mode 100644
index 00000000..b2231a75
--- /dev/null
+++ b/src/codecs/dr_mp3.h
@@ -0,0 +1,4785 @@
+/*
+MP3 audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
+dr_mp3 - v0.6.33 - 2022-04-10
+
+David Reid - mackron@gmail.com
+
+GitHub: https://github.com/mackron/dr_libs
+
+Based on minimp3 (https://github.com/lieff/minimp3) which is where the real work was done. See the bottom of this file for differences between minimp3 and dr_mp3.
+*/
+
+/*
+RELEASE NOTES - VERSION 0.6
+===========================
+Version 0.6 includes breaking changes with the configuration of decoders. The ability to customize the number of output channels and the sample rate has been
+removed. You must now use the channel count and sample rate reported by the MP3 stream itself, and all channel and sample rate conversion must be done
+yourself.
+
+
+Changes to Initialization
+-------------------------
+Previously, `drmp3_init()`, etc. took a pointer to a `drmp3_config` object that allowed you to customize the output channels and sample rate. This has been
+removed. If you need the old behaviour you will need to convert the data yourself or just not upgrade. The following APIs have changed.
+
+    `drmp3_init()`
+    `drmp3_init_memory()`
+    `drmp3_init_file()`
+
+
+Miscellaneous Changes
+---------------------
+Support for loading a file from a `wchar_t` string has been added via the `drmp3_init_file_w()` API.
+*/
+
+/*
+Introducation
+=============
+dr_mp3 is a single file library. To use it, do something like the following in one .c file.
+
+    ```c
+    #define DR_MP3_IMPLEMENTATION
+    #include "dr_mp3.h"
+    ```
+
+You can then #include this file in other parts of the program as you would with any other header file. To decode audio data, do something like the following:
+
+    ```c
+    drmp3 mp3;
+    if (!drmp3_init_file(&mp3, "MySong.mp3", NULL)) {
+        // Failed to open file
+    }
+
+    ...
+
+    drmp3_uint64 framesRead = drmp3_read_pcm_frames_f32(pMP3, framesToRead, pFrames);
+    ```
+
+The drmp3 object is transparent so you can get access to the channel count and sample rate like so:
+
+    ```
+    drmp3_uint32 channels = mp3.channels;
+    drmp3_uint32 sampleRate = mp3.sampleRate;
+    ```
+
+The example above initializes a decoder from a file, but you can also initialize it from a block of memory and read and seek callbacks with
+`drmp3_init_memory()` and `drmp3_init()` respectively.
+
+You do not need to do any annoying memory management when reading PCM frames - this is all managed internally. You can request any number of PCM frames in each
+call to `drmp3_read_pcm_frames_f32()` and it will return as many PCM frames as it can, up to the requested amount.
+
+You can also decode an entire file in one go with `drmp3_open_and_read_pcm_frames_f32()`, `drmp3_open_memory_and_read_pcm_frames_f32()` and
+`drmp3_open_file_and_read_pcm_frames_f32()`.
+
+
+Build Options
+=============
+#define these options before including this file.
+
+#define DR_MP3_NO_STDIO
+  Disable drmp3_init_file(), etc.
+
+#define DR_MP3_NO_SIMD
+  Disable SIMD optimizations.
+*/
+
+#ifndef dr_mp3_h
+#define dr_mp3_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DRMP3_STRINGIFY(x)      #x
+#define DRMP3_XSTRINGIFY(x)     DRMP3_STRINGIFY(x)
+
+#define DRMP3_VERSION_MAJOR     0
+#define DRMP3_VERSION_MINOR     6
+#define DRMP3_VERSION_REVISION  33
+#define DRMP3_VERSION_STRING    DRMP3_XSTRINGIFY(DRMP3_VERSION_MAJOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_MINOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_REVISION)
+
+#include <stddef.h> /* For size_t. */
+
+/* Sized types. */
+typedef   signed char           drmp3_int8;
+typedef unsigned char           drmp3_uint8;
+typedef   signed short          drmp3_int16;
+typedef unsigned short          drmp3_uint16;
+typedef   signed int            drmp3_int32;
+typedef unsigned int            drmp3_uint32;
+#if defined(_MSC_VER) && !defined(__clang__)
+    typedef   signed __int64    drmp3_int64;
+    typedef unsigned __int64    drmp3_uint64;
+#else
+    #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
+        #pragma GCC diagnostic push
+        #pragma GCC diagnostic ignored "-Wlong-long"
+        #if defined(__clang__)
+            #pragma GCC diagnostic ignored "-Wc++11-long-long"
+        #endif
+    #endif
+    typedef   signed long long  drmp3_int64;
+    typedef unsigned long long  drmp3_uint64;
+    #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
+        #pragma GCC diagnostic pop
+    #endif
+#endif
+#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(_M_ARM64) || defined(__powerpc64__)
+    typedef drmp3_uint64        drmp3_uintptr;
+#else
+    typedef drmp3_uint32        drmp3_uintptr;
+#endif
+typedef drmp3_uint8             drmp3_bool8;
+typedef drmp3_uint32            drmp3_bool32;
+#define DRMP3_TRUE              1
+#define DRMP3_FALSE             0
+
+#if !defined(DRMP3_API)
+    #if defined(DRMP3_DLL)
+        #if defined(_WIN32)
+            #define DRMP3_DLL_IMPORT  __declspec(dllimport)
+            #define DRMP3_DLL_EXPORT  __declspec(dllexport)
+            #define DRMP3_DLL_PRIVATE static
+        #else
+            #if defined(__GNUC__) && __GNUC__ >= 4
+                #define DRMP3_DLL_IMPORT  __attribute__((visibility("default")))
+                #define DRMP3_DLL_EXPORT  __attribute__((visibility("default")))
+                #define DRMP3_DLL_PRIVATE __attribute__((visibility("hidden")))
+            #else
+                #define DRMP3_DLL_IMPORT
+                #define DRMP3_DLL_EXPORT
+                #define DRMP3_DLL_PRIVATE static
+            #endif
+        #endif
+
+        #if defined(DR_MP3_IMPLEMENTATION) || defined(DRMP3_IMPLEMENTATION)
+            #define DRMP3_API  DRMP3_DLL_EXPORT
+        #else
+            #define DRMP3_API  DRMP3_DLL_IMPORT
+        #endif
+        #define DRMP3_PRIVATE DRMP3_DLL_PRIVATE
+    #else
+        #define DRMP3_API extern
+        #define DRMP3_PRIVATE static
+    #endif
+#endif
+
+typedef drmp3_int32 drmp3_result;
+#define DRMP3_SUCCESS                        0
+#define DRMP3_ERROR                         -1   /* A generic error. */
+#define DRMP3_INVALID_ARGS                  -2
+#define DRMP3_INVALID_OPERATION             -3
+#define DRMP3_OUT_OF_MEMORY                 -4
+#define DRMP3_OUT_OF_RANGE                  -5
+#define DRMP3_ACCESS_DENIED                 -6
+#define DRMP3_DOES_NOT_EXIST                -7
+#define DRMP3_ALREADY_EXISTS                -8
+#define DRMP3_TOO_MANY_OPEN_FILES           -9
+#define DRMP3_INVALID_FILE                  -10
+#define DRMP3_TOO_BIG                       -11
+#define DRMP3_PATH_TOO_LONG                 -12
+#define DRMP3_NAME_TOO_LONG                 -13
+#define DRMP3_NOT_DIRECTORY                 -14
+#define DRMP3_IS_DIRECTORY                  -15
+#define DRMP3_DIRECTORY_NOT_EMPTY           -16
+#define DRMP3_END_OF_FILE                   -17
+#define DRMP3_NO_SPACE                      -18
+#define DRMP3_BUSY                          -19
+#define DRMP3_IO_ERROR                      -20
+#define DRMP3_INTERRUPT                     -21
+#define DRMP3_UNAVAILABLE                   -22
+#define DRMP3_ALREADY_IN_USE                -23
+#define DRMP3_BAD_ADDRESS                   -24
+#define DRMP3_BAD_SEEK                      -25
+#define DRMP3_BAD_PIPE                      -26
+#define DRMP3_DEADLOCK                      -27
+#define DRMP3_TOO_MANY_LINKS                -28
+#define DRMP3_NOT_IMPLEMENTED               -29
+#define DRMP3_NO_MESSAGE                    -30
+#define DRMP3_BAD_MESSAGE                   -31
+#define DRMP3_NO_DATA_AVAILABLE             -32
+#define DRMP3_INVALID_DATA                  -33
+#define DRMP3_TIMEOUT                       -34
+#define DRMP3_NO_NETWORK                    -35
+#define DRMP3_NOT_UNIQUE                    -36
+#define DRMP3_NOT_SOCKET                    -37
+#define DRMP3_NO_ADDRESS                    -38
+#define DRMP3_BAD_PROTOCOL                  -39
+#define DRMP3_PROTOCOL_UNAVAILABLE          -40
+#define DRMP3_PROTOCOL_NOT_SUPPORTED        -41
+#define DRMP3_PROTOCOL_FAMILY_NOT_SUPPORTED -42
+#define DRMP3_ADDRESS_FAMILY_NOT_SUPPORTED  -43
+#define DRMP3_SOCKET_NOT_SUPPORTED          -44
+#define DRMP3_CONNECTION_RESET              -45
+#define DRMP3_ALREADY_CONNECTED             -46
+#define DRMP3_NOT_CONNECTED                 -47
+#define DRMP3_CONNECTION_REFUSED            -48
+#define DRMP3_NO_HOST                       -49
+#define DRMP3_IN_PROGRESS                   -50
+#define DRMP3_CANCELLED                     -51
+#define DRMP3_MEMORY_ALREADY_MAPPED         -52
+#define DRMP3_AT_END                        -53
+
+
+#define DRMP3_MAX_PCM_FRAMES_PER_MP3_FRAME  1152
+#define DRMP3_MAX_SAMPLES_PER_FRAME         (DRMP3_MAX_PCM_FRAMES_PER_MP3_FRAME*2)
+
+#ifdef _MSC_VER
+    #define DRMP3_INLINE __forceinline
+#elif defined(__GNUC__)
+    /*
+    I've had a bug report where GCC is emitting warnings about functions possibly not being inlineable. This warning happens when
+    the __attribute__((always_inline)) attribute is defined without an "inline" statement. I think therefore there must be some
+    case where "__inline__" is not always defined, thus the compiler emitting these warnings. When using -std=c89 or -ansi on the
+    command line, we cannot use the "inline" keyword and instead need to use "__inline__". In an attempt to work around this issue
+    I am using "__inline__" only when we're compiling in strict ANSI mode.
+    */
+    #if defined(__STRICT_ANSI__)
+        #define DRMP3_GNUC_INLINE_HINT __inline__
+    #else
+        #define DRMP3_GNUC_INLINE_HINT inline
+    #endif
+
+    #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)) || defined(__clang__)
+        #define DRMP3_INLINE DRMP3_GNUC_INLINE_HINT __attribute__((always_inline))
+    #else
+        #define DRMP3_INLINE DRMP3_GNUC_INLINE_HINT
+    #endif
+#elif defined(__WATCOMC__)
+    #define DRMP3_INLINE __inline
+#else
+    #define DRMP3_INLINE
+#endif
+
+
+DRMP3_API void drmp3_version(drmp3_uint32* pMajor, drmp3_uint32* pMinor, drmp3_uint32* pRevision);
+DRMP3_API const char* drmp3_version_string(void);
+
+
+/*
+Low Level Push API
+==================
+*/
+typedef struct
+{
+    int frame_bytes, channels, hz, layer, bitrate_kbps;
+} drmp3dec_frame_info;
+
+typedef struct
+{
+    float mdct_overlap[2][9*32], qmf_state[15*2*32];
+    int reserv, free_format_bytes;
+    drmp3_uint8 header[4], reserv_buf[511];
+} drmp3dec;
+
+/* Initializes a low level decoder. */
+DRMP3_API void drmp3dec_init(drmp3dec *dec);
+
+/* Reads a frame from a low level decoder. */
+DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int mp3_bytes, void *pcm, drmp3dec_frame_info *info);
+
+/* Helper for converting between f32 and s16. */
+DRMP3_API void drmp3dec_f32_to_s16(const float *in, drmp3_int16 *out, size_t num_samples);
+
+
+
+/*
+Main API (Pull API)
+===================
+*/
+typedef enum
+{
+    drmp3_seek_origin_start,
+    drmp3_seek_origin_current
+} drmp3_seek_origin;
+
+typedef struct
+{
+    drmp3_uint64 seekPosInBytes;        /* Points to the first byte of an MP3 frame. */
+    drmp3_uint64 pcmFrameIndex;         /* The index of the PCM frame this seek point targets. */
+    drmp3_uint16 mp3FramesToDiscard;    /* The number of whole MP3 frames to be discarded before pcmFramesToDiscard. */
+    drmp3_uint16 pcmFramesToDiscard;    /* The number of leading samples to read and discard. These are discarded after mp3FramesToDiscard. */
+} drmp3_seek_point;
+
+/*
+Callback for when data is read. Return value is the number of bytes actually read.
+
+pUserData   [in]  The user data that was passed to drmp3_init(), drmp3_open() and family.
+pBufferOut  [out] The output buffer.
+bytesToRead [in]  The number of bytes to read.
+
+Returns the number of bytes actually read.
+
+A return value of less than bytesToRead indicates the end of the stream. Do _not_ return from this callback until
+either the entire bytesToRead is filled or you have reached the end of the stream.
+*/
+typedef size_t (* drmp3_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead);
+
+/*
+Callback for when data needs to be seeked.
+
+pUserData [in] The user data that was passed to drmp3_init(), drmp3_open() and family.
+offset    [in] The number of bytes to move, relative to the origin. Will never be negative.
+origin    [in] The origin of the seek - the current position or the start of the stream.
+
+Returns whether or not the seek was successful.
+
+Whether or not it is relative to the beginning or current position is determined by the "origin" parameter which
+will be either drmp3_seek_origin_start or drmp3_seek_origin_current.
+*/
+typedef drmp3_bool32 (* drmp3_seek_proc)(void* pUserData, int offset, drmp3_seek_origin origin);
+
+typedef struct
+{
+    void* pUserData;
+    void* (* onMalloc)(size_t sz, void* pUserData);
+    void* (* onRealloc)(void* p, size_t sz, void* pUserData);
+    void  (* onFree)(void* p, void* pUserData);
+} drmp3_allocation_callbacks;
+
+typedef struct
+{
+    drmp3_uint32 channels;
+    drmp3_uint32 sampleRate;
+} drmp3_config;
+
+typedef struct
+{
+    drmp3dec decoder;
+    drmp3dec_frame_info frameInfo;
+    drmp3_uint32 channels;
+    drmp3_uint32 sampleRate;
+    drmp3_read_proc onRead;
+    drmp3_seek_proc onSeek;
+    void* pUserData;
+    drmp3_allocation_callbacks allocationCallbacks;
+    drmp3_uint32 mp3FrameChannels;      /* The number of channels in the currently loaded MP3 frame. Internal use only. */
+    drmp3_uint32 mp3FrameSampleRate;    /* The sample rate of the currently loaded MP3 frame. Internal use only. */
+    drmp3_uint32 pcmFramesConsumedInMP3Frame;
+    drmp3_uint32 pcmFramesRemainingInMP3Frame;
+    drmp3_uint8 pcmFrames[sizeof(float)*DRMP3_MAX_SAMPLES_PER_FRAME];  /* <-- Multipled by sizeof(float) to ensure there's enough room for DR_MP3_FLOAT_OUTPUT. */
+    drmp3_uint64 currentPCMFrame;       /* The current PCM frame, globally, based on the output sample rate. Mainly used for seeking. */
+    drmp3_uint64 streamCursor;          /* The current byte the decoder is sitting on in the raw stream. */
+    drmp3_seek_point* pSeekPoints;      /* NULL by default. Set with drmp3_bind_seek_table(). Memory is owned by the client. dr_mp3 will never attempt to free this pointer. */
+    drmp3_uint32 seekPointCount;        /* The number of items in pSeekPoints. When set to 0 assumes to no seek table. Defaults to zero. */
+    size_t dataSize;
+    size_t dataCapacity;
+    size_t dataConsumed;
+    drmp3_uint8* pData;
+    drmp3_bool32 atEnd : 1;
+    struct
+    {
+        const drmp3_uint8* pData;
+        size_t dataSize;
+        size_t currentReadPos;
+    } memory;   /* Only used for decoders that were opened against a block of memory. */
+} drmp3;
+
+/*
+Initializes an MP3 decoder.
+
+onRead    [in]           The function to call when data needs to be read from the client.
+onSeek    [in]           The function to call when the read position of the client data needs to move.
+pUserData [in, optional] A pointer to application defined data that will be passed to onRead and onSeek.
+
+Returns true if successful; false otherwise.
+
+Close the loader with drmp3_uninit().
+
+See also: drmp3_init_file(), drmp3_init_memory(), drmp3_uninit()
+*/
+DRMP3_API drmp3_bool32 drmp3_init(drmp3* pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, const drmp3_allocation_callbacks* pAllocationCallbacks);
+
+/*
+Initializes an MP3 decoder from a block of memory.
+
+This does not create a copy of the data. It is up to the application to ensure the buffer remains valid for
+the lifetime of the drmp3 object.
+
+The buffer should contain the contents of the entire MP3 file.
+*/
+DRMP3_API drmp3_bool32 drmp3_init_memory(drmp3* pMP3, const void* pData, size_t dataSize, const drmp3_allocation_callbacks* pAllocationCallbacks);
+
+#ifndef DR_MP3_NO_STDIO
+/*
+Initializes an MP3 decoder from a file.
+
+This holds the internal FILE object until drmp3_uninit() is called. Keep this in mind if you're caching drmp3
+objects because the operating system may restrict the number of file handles an application can have open at
+any given time.
+*/
+DRMP3_API drmp3_bool32 drmp3_init_file(drmp3* pMP3, const char* pFilePath, const drmp3_allocation_callbacks* pAllocationCallbacks);
+DRMP3_API drmp3_bool32 drmp3_init_file_w(drmp3* pMP3, const wchar_t* pFilePath, const drmp3_allocation_callbacks* pAllocationCallbacks);
+#endif
+
+/*
+Uninitializes an MP3 decoder.
+*/
+DRMP3_API void drmp3_uninit(drmp3* pMP3);
+
+/*
+Reads PCM frames as interleaved 32-bit IEEE floating point PCM.
+
+Note that framesToRead specifies the number of PCM frames to read, _not_ the number of MP3 frames.
+*/
+DRMP3_API drmp3_uint64 drmp3_read_pcm_frames_f32(drmp3* pMP3, drmp3_uint64 framesToRead, float* pBufferOut);
+
+/*
+Reads PCM frames as interleaved signed 16-bit integer PCM.
+
+Note that framesToRead specifies the number of PC

(Patch may be truncated, please check the link at the top of this post.)