]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - snd_xmp.c
sv_save: Call CL_Disconnect and ToggleMenu via hook
[xonotic/darkplaces.git] / snd_xmp.c
index 7fde6137ebb002e6512e86760e35e7a903d31b19..9876803d571fbcfc8c0922ba1d513b5100d1f2d5 100644 (file)
--- a/snd_xmp.c
+++ b/snd_xmp.c
  */
 
 
-#include "quakedef.h"
+#include "darkplaces.h"
 #include "snd_main.h"
 #include "snd_xmp.h"
+#include "sound.h"
 
 #ifdef LINK_TO_LIBXMP
 #include <xmp.h>
+#if ((XMP_VERCODE+0) < 0x040200)
+#error libxmp version 4.2 or newer is required when linking to libxmp
+#endif
 
 /* libxmp API */
 // Version and player information
@@ -36,7 +40,7 @@
 #define qxmp_create_context xmp_create_context // xmp_context xmp_create_context()
 #define qxmp_free_context xmp_free_context // void xmp_free_context(xmp_context c)
 // Module loading
-#define qxmp_test_module xmp_test_module // int xmp_test_module(char *path, struct xmp_test_info *test_info)
+//#define qxmp_test_module xmp_test_module // int xmp_test_module(char *path, struct xmp_test_info *test_info)
 //#define qxmp_load_module xmp_load_module // int xmp_load_module(xmp_context c, char *path)
 #define qxmp_load_module_from_memory xmp_load_module_from_memory // int xmp_load_module_from_memory(xmp_context c, void *mem, long size)
 //#define qxmp_load_module_from_file xmp_load_module_from_file // int xmp_load_module_from_file(xmp_context c, FILE *f, long size)
 
 #define xmp_dll 1
 
-qboolean XMP_OpenLibrary (void)
-{
-       Con_Printf("Linked against libxmp version %s (0x0%x)\n", qxmp_version, qxmp_vercode);
-       return true;
-}
+qbool XMP_OpenLibrary (void) {return true;}
 void XMP_CloseLibrary (void) {}
 #else
 
@@ -122,8 +122,8 @@ void XMP_CloseLibrary (void) {}
 //#define XMP_MAX_ENV_POINTS   32      /* Max number of envelope points */
 #define XMP_MAX_MOD_LENGTH     256     /* Max number of patterns in module */
 //#define XMP_MAX_CHANNELS     64      /* Max number of channels in module */
-//#define XMP_MAX_SRATE                49170   /* max sampling rate (Hz) */
-//#define XMP_MIN_SRATE                4000    /* min sampling rate (Hz) */
+#define XMP_MAX_SRATE          49170   /* max sampling rate (Hz) */
+#define XMP_MIN_SRATE          4000    /* min sampling rate (Hz) */
 //#define XMP_MIN_BPM          20      /* min BPM */
 #define XMP_MAX_FRAMESIZE      (5 * XMP_MAX_SRATE * 2 / XMP_MIN_BPM)
 
@@ -144,11 +144,11 @@ static const char **qxmp_version;
 static const unsigned int *qxmp_vercode;
 
 struct xmp_channel {
-//     int pan;                        /* Channel pan (0x80 is center) */
-//     int vol;                        /* Channel volume */
-//#define XMP_CHANNEL_SYNTH    (1 << 0)  /* Channel is synthesized */
-//#define XMP_CHANNEL_MUTE     (1 << 1)  /* Channel is muted */
-//     int flg;                        /* Channel flags */
+       int pan;                        /* Channel pan (0x80 is center) */
+       int vol;                        /* Channel volume */
+#define XMP_CHANNEL_SYNTH      (1 << 0)  /* Channel is synthesized */
+#define XMP_CHANNEL_MUTE       (1 << 1)  /* Channel is muted */
+       int flg;                        /* Channel flags */
 };
 
 //struct xmp_sequence {
@@ -178,10 +178,10 @@ struct xmp_module {
        unsigned char xxo[XMP_MAX_MOD_LENGTH];  /* Orders */
 };
 
-struct xmp_test_info {
+//struct xmp_test_info {
 //     char name[XMP_NAME_SIZE];       /* Module title */
 //     char type[XMP_NAME_SIZE];       /* Module format */
-};
+//};
 
 struct xmp_module_info {
        unsigned char md5[16];          /* MD5 message digest */
@@ -192,7 +192,8 @@ struct xmp_module_info {
        struct xmp_sequence *seq_data;  /* Pointer to sequence data */
 };
 
-struct xmp_frame_info {                        /* Current frame information */
+struct xmp_frame_info
+// {                   /* Current frame information */
 //     int pos;                        /* Current position */
 //     int pattern;                    /* Current pattern */
 //     int row;                        /* Current row in pattern */
@@ -224,12 +225,13 @@ struct xmp_frame_info {                   /* Current frame information */
 //             unsigned char reserved; /* Reserved */
 //             struct xmp_event event; /* Current track event */
 //     } channel_info[XMP_MAX_CHANNELS];
-};
+//}
+;
 
 // Functions exported from libxmp
 static xmp_context (*qxmp_create_context)  (void);
 static void        (*qxmp_free_context)    (xmp_context);
-static int         (*qxmp_test_module)     (char *, struct xmp_test_info *);
+//static int         (*qxmp_test_module)     (char *, struct xmp_test_info *);
 //static int         (*qxmp_load_module)     (xmp_context, char *);
 //static void        (*qxmp_scan_module)     (xmp_context);
 static void        (*qxmp_release_module)  (xmp_context);
@@ -287,7 +289,7 @@ static dllfunction_t xmpfuncs[] =
        {"xmp_create_context",          (void **) &qxmp_create_context},
        {"xmp_free_context",            (void **) &qxmp_free_context},
        // Module loading
-       {"xmp_test_module",             (void **) &qxmp_test_module},
+//     {"xmp_test_module",             (void **) &qxmp_test_module},
 //     {"xmp_load_module",             (void **) &qxmp_load_module},
        {"xmp_load_module_from_memory", (void **) &qxmp_load_module_from_memory}, // since libxmp 4.2.0
 //     {"xmp_load_module_from_file",   (void **) &qxmp_load_module_from_file},   // since libxmp 4.3.0
@@ -344,11 +346,12 @@ XMP_OpenLibrary
 Try to load the libxmp DLL
 ====================
 */
-qboolean XMP_OpenLibrary (void)
+qbool XMP_OpenLibrary (void)
 {
        const char* dllnames_xmp [] =
        {
 #if defined(WIN32)
+               "libxmp-4.dll",
                "libxmp.dll",
 #elif defined(MACOSX) // FIXME: untested, please test a mac os build
                "libxmp.4.dylib",
@@ -364,19 +367,20 @@ qboolean XMP_OpenLibrary (void)
                return true;
 
 // COMMANDLINEOPTION: Sound: -noxmp disables xmp module sound support
-       if (COM_CheckParm("-noxmp"))
+       if (Sys_CheckParm("-noxmp"))
                return false;
 
        // Load the DLL
-       if (Sys_LoadLibrary (dllnames_xmp, &xmp_dll, xmpfuncs))
+       if (Sys_LoadDependency (dllnames_xmp, &xmp_dll, xmpfuncs))
        {
                if (*qxmp_vercode < 0x040200)
                {
                        Con_Printf("Found incompatible XMP library version %s, not loading. (4.2.0 or higher required)\n", *qxmp_version);
-                       Sys_UnloadLibrary (&xmp_dll);
+                       Sys_FreeLibrary (&xmp_dll);
                        return false;
                }
-               Con_Printf("XMP library loaded, version %s (0x0%x)\n", *qxmp_version, *qxmp_vercode);
+               if (developer_loading.integer >= 1)
+                       Con_Printf("XMP library loaded, version %s (0x0%x)\n", *qxmp_version, *qxmp_vercode);
                return true;
        }
        else
@@ -393,7 +397,7 @@ Unload the libxmp DLL
 */
 void XMP_CloseLibrary (void)
 {
-       Sys_UnloadLibrary (&xmp_dll);
+       Sys_FreeLibrary (&xmp_dll);
 }
 
 #endif
@@ -461,9 +465,22 @@ static void XMP_GetSamplesFloat(channel_t *ch, sfx_t *sfx, int firstsampleframe,
                }
 
                // start playing the loaded file
-               if (sfx->format.width == 1)    { format |= XMP_FORMAT_8BIT; } // else 16bit
+               if (sfx->format.width == 1)    { format |= XMP_FORMAT_8BIT | XMP_FORMAT_UNSIGNED; } // else 16bit
                if (sfx->format.channels == 1) { format |= XMP_FORMAT_MONO; } // else stereo
-               if (qxmp_start_player(per_ch->playercontext, sfx->format.speed, format) < 0) // FIXME: only if speed is in XMP acceptable range, else default to 48khz and let DP mix
+
+               if (qxmp_start_player(per_ch->playercontext, sfx->format.speed, format) < 0)
+               {
+                       Mem_Free(per_ch);
+                       return;
+               }
+               /* percentual left/right channel separation, default is 70. */
+               if (sfx->format.channels == 2 && (qxmp_set_player(per_ch->playercontext, XMP_PLAYER_MIX, 50) != 0))
+               {
+                       Mem_Free(per_ch);
+                       return;
+               }
+               /* interpolation type, default is XMP_INTERP_LINEAR */
+               if (qxmp_set_player(per_ch->playercontext, XMP_PLAYER_INTERP, XMP_INTERP_SPLINE) != 0)
                {
                        Mem_Free(per_ch);
                        return;
@@ -576,7 +593,7 @@ XMP_LoadModFile
 Load an XMP module file into memory
 ===============
 */
-qboolean XMP_LoadModFile(const char *filename, sfx_t *sfx)
+qbool XMP_LoadModFile(const char *filename, sfx_t *sfx)
 {
        fs_offset_t filesize;
        unsigned char *data;
@@ -590,7 +607,7 @@ qboolean XMP_LoadModFile(const char *filename, sfx_t *sfx)
 #endif
 
 // COMMANDLINEOPTION: Sound: -noxmp disables xmp module sound support
-       if (COM_CheckParm("-noxmp"))
+       if (Sys_CheckParm("-noxmp"))
                return false;
 
        // Return if already loaded
@@ -631,23 +648,23 @@ qboolean XMP_LoadModFile(const char *filename, sfx_t *sfx)
        // set dp sfx
        sfx->memsize += sizeof(*per_sfx);
        sfx->memsize += filesize; // total memory used (including sfx_t and fetcher data)
-//     sfx->format // format describing the audio data that fetcher->getsamplesfloat shall return
-       sfx->format.speed = 48000; // default to this sample rate
-       sfx->format.width = 2;  // default to 16 bit samples
-//     sfx->format.width = 1; // 8-bit
-       sfx->format.channels = 2; // default to stereo
-//     sfx->format.channels = 1; // mono
+       if (S_GetSoundRate() > XMP_MAX_SRATE)
+               sfx->format.speed = 48000;
+       else if (S_GetSoundRate() < XMP_MIN_SRATE)
+               sfx->format.speed = 8000;
+       else
+               sfx->format.speed = S_GetSoundRate();
+       sfx->format.width = S_GetSoundWidth();  // 2 = 16 bit samples
+       sfx->format.channels = S_GetSoundChannels();
        sfx->flags |= SFXFLAG_STREAMED; // cf SFXFLAG_* defines
-//     sfx->total_length // in (pcm) sample frames
-       sfx->total_length = 1<<30; // 2147384647; // they always loop (FIXME this breaks after 6 hours, we need support for a real "infinite" value!)
+       sfx->total_length = 1<<30; // 2147384647; // in (pcm) sample frames - they always loop (FIXME this breaks after 6 hours, we need support for a real "infinite" value!)
        sfx->loopstart = sfx->total_length; // (modplug does it) in sample frames. equals total_length if not looped
        sfx->fetcher_data = per_sfx;
        sfx->fetcher = &xmp_fetcher;
-//     sfx->volume_mult // for replay gain (multiplier to apply)
-//     sfx->volume_peak // for replay gain (highest peak); if set to 0, ReplayGain isn't supported
+       sfx->volume_peak = 0;
 
        qxmp_get_module_info(xc, &mi);
-       if (developer_loading.integer >= 1)
+       if (developer_loading.integer >= 2)
        {
                Con_Printf("Decoding module (libxmp):\n"
                        "    Module name  : %s\n"
@@ -666,7 +683,7 @@ qboolean XMP_LoadModFile(const char *filename, sfx_t *sfx)
                        mi.mod->spd, mi.mod->bpm, mi.mod->rst, mi.mod->gvl
                );
        }
-       else if (developer.integer >= 1)
+       else if (developer_loading.integer == 1)
                Con_Printf("Decoding module (libxmp) \"%s\" (%s)\n", mi.mod->name, mi.mod->type);
 
        qxmp_free_context(xc);