*/
-#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
#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
//#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)
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 {
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 */
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 */
// 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);
{"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
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",
return true;
// COMMANDLINEOPTION: Sound: -noxmp disables xmp module sound support
- if (COM_CheckParm("-noxmp"))
+ if (Sys_CheckParm("-noxmp"))
return false;
// Load the DLL
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
*/
void XMP_CloseLibrary (void)
{
- Sys_UnloadLibrary (&xmp_dll);
+ Sys_FreeLibrary (&xmp_dll);
}
#endif
}
// 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;
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;
#endif
// COMMANDLINEOPTION: Sound: -noxmp disables xmp module sound support
- if (COM_CheckParm("-noxmp"))
+ if (Sys_CheckParm("-noxmp"))
return false;
// Return if already loaded
// 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"
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);