2 Copyright (C) 2014 nyov <nyov@nexnode.net>
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 * libxmp is licensed under the terms of the Lesser General Public License 2.1
29 #if ((XMP_VERCODE+0) < 0x040200)
30 #error libxmp version 4.2 or newer is required when linking to libxmp
34 // Version and player information
35 #define qxmp_version xmp_version // const char *xmp_version
36 #define qxmp_vercode xmp_vercode // const unsigned int xmp_vercode
37 //#define qxmp_get_format_list xmp_get_format_list // char **xmp_get_format_list()
39 #define qxmp_create_context xmp_create_context // xmp_context xmp_create_context()
40 #define qxmp_free_context xmp_free_context // void xmp_free_context(xmp_context c)
42 //#define qxmp_test_module xmp_test_module // int xmp_test_module(char *path, struct xmp_test_info *test_info)
43 //#define qxmp_load_module xmp_load_module // int xmp_load_module(xmp_context c, char *path)
44 #define qxmp_load_module_from_memory xmp_load_module_from_memory // int xmp_load_module_from_memory(xmp_context c, void *mem, long size)
45 //#define qxmp_load_module_from_file xmp_load_module_from_file // int xmp_load_module_from_file(xmp_context c, FILE *f, long size)
46 #define qxmp_release_module xmp_release_module // void xmp_release_module(xmp_context c)
47 //#define qxmp_scan_module xmp_scan_module // void xmp_scan_module(xmp_context c)
48 #define qxmp_get_module_info xmp_get_module_info // void xmp_get_module_info(xmp_context c, struct xmp_module_info *info)
50 #define qxmp_start_player xmp_start_player // int xmp_start_player(xmp_context c, int rate, int format)
51 #define qxmp_play_frame xmp_play_frame // int xmp_play_frame(xmp_context c)
52 #define qxmp_play_buffer xmp_play_buffer // int xmp_play_buffer(xmp_context c, void *buffer, int size, int loop)
53 #define qxmp_get_frame_info xmp_get_frame_info // void xmp_get_frame_info(xmp_context c, struct xmp_frame_info *info)
54 #define qxmp_end_player xmp_end_player // void xmp_end_player(xmp_context c)
56 //#define qxmp_next_position xmp_next_position // int xmp_next_position(xmp_context c)
57 //#define qxmp_prev_position xmp_prev_position// int xmp_prev_position(xmp_context c)
58 //#define qxmp_set_position xmp_set_position // int xmp_set_position(xmp_context c, int pos)
59 //#define qxmp_stop_module xmp_stop_module // void xmp_stop_module(xmp_context c)
60 //#define qxmp_restart_module xmp_restart_module // void xmp_restart_module(xmp_context c)
61 //#define qxmp_seek_time xmp_seek_time // int xmp_seek_time(xmp_context c, int time)
62 //#define qxmp_channel_mute xmp_channel_mute // int xmp_channel_mute(xmp_context c, int channel, int status)
63 //#define qxmp_channel_vol xmp_channel_vol // int xmp_channel_vol(xmp_context c, int channel, int vol)
64 //#define qxmp_inject_event xmp_inject_event // void xmp_inject_event(xmp_context c, int channel, struct xmp_event *event)
65 // Player parameter setting
66 //#define qxmp_set_instrument_path xmp_set_instrument_path // int xmp_set_instrument_path(xmp_context c, char *path)
67 #define qxmp_get_player xmp_get_player // int xmp_get_player(xmp_context c, int param)
68 #define qxmp_set_player xmp_set_player // int xmp_set_player(xmp_context c, int param, int val)
72 qboolean XMP_OpenLibrary (void) {return true;}
73 void XMP_CloseLibrary (void) {}
78 =================================================================
80 definitions from xmp.h
82 =================================================================
85 // constants from libxmp
86 #define XMP_NAME_SIZE 64 /* Size of module name and type */
88 /* sample format flags */
89 #define XMP_FORMAT_8BIT (1 << 0) /* Mix to 8-bit instead of 16 */
90 #define XMP_FORMAT_UNSIGNED (1 << 1) /* Mix to unsigned samples */
91 #define XMP_FORMAT_MONO (1 << 2) /* Mix to mono instead of stereo */
93 /* player parameters */
94 #define XMP_PLAYER_AMP 0 /* Amplification factor */
95 #define XMP_PLAYER_MIX 1 /* Stereo mixing */
96 #define XMP_PLAYER_INTERP 2 /* Interpolation type */
97 #define XMP_PLAYER_DSP 3 /* DSP effect flags */
98 #define XMP_PLAYER_FLAGS 4 /* Player flags */
99 #define XMP_PLAYER_CFLAGS 5 /* Player flags for current module */
100 #define XMP_PLAYER_SMPCTL 6 /* Sample control flags */
101 #define XMP_PLAYER_VOLUME 7 /* Player module volume */
102 #define XMP_PLAYER_STATE 8 /* Internal player state */
103 #define XMP_PLAYER_SMIX_VOLUME 9 /* SMIX volume */
104 #define XMP_PLAYER_DEFPAN 10 /* Default pan setting */
106 /* interpolation types */
107 #define XMP_INTERP_NEAREST 0 /* Nearest neighbor */
108 #define XMP_INTERP_LINEAR 1 /* Linear (default) */
109 #define XMP_INTERP_SPLINE 2 /* Cubic spline */
112 #define XMP_STATE_UNLOADED 0 /* Context created */
113 #define XMP_STATE_LOADED 1 /* Module loaded */
114 #define XMP_STATE_PLAYING 2 /* Module playing */
117 #define XMP_SMPCTL_SKIP (1 << 0) /* Don't load samples */
120 //#define XMP_MAX_KEYS 121 /* Number of valid keys */
121 //#define XMP_MAX_ENV_POINTS 32 /* Max number of envelope points */
122 #define XMP_MAX_MOD_LENGTH 256 /* Max number of patterns in module */
123 //#define XMP_MAX_CHANNELS 64 /* Max number of channels in module */
124 #define XMP_MAX_SRATE 49170 /* max sampling rate (Hz) */
125 #define XMP_MIN_SRATE 4000 /* min sampling rate (Hz) */
126 //#define XMP_MIN_BPM 20 /* min BPM */
127 #define XMP_MAX_FRAMESIZE (5 * XMP_MAX_SRATE * 2 / XMP_MIN_BPM)
131 #define XMP_ERROR_INTERNAL 2 /* Internal error */
132 #define XMP_ERROR_FORMAT 3 /* Unsupported module format */
133 #define XMP_ERROR_LOAD 4 /* Error loading file */
134 #define XMP_ERROR_DEPACK 5 /* Error depacking file */
135 #define XMP_ERROR_SYSTEM 6 /* System error */
136 #define XMP_ERROR_INVALID 7 /* Invalid parameter */
137 #define XMP_ERROR_STATE 8 /* Invalid player state */
140 typedef char *xmp_context;
142 static const char **qxmp_version;
143 static const unsigned int *qxmp_vercode;
146 int pan; /* Channel pan (0x80 is center) */
147 int vol; /* Channel volume */
148 #define XMP_CHANNEL_SYNTH (1 << 0) /* Channel is synthesized */
149 #define XMP_CHANNEL_MUTE (1 << 1) /* Channel is muted */
150 int flg; /* Channel flags */
153 //struct xmp_sequence {
159 char name[XMP_NAME_SIZE]; /* Module title */
160 char type[XMP_NAME_SIZE]; /* Module format */
161 int pat; /* Number of patterns */
162 int trk; /* Number of tracks */
163 int chn; /* Tracks per pattern */
164 int ins; /* Number of instruments */
165 int smp; /* Number of samples */
166 int spd; /* Initial speed */
167 int bpm; /* Initial BPM */
168 int len; /* Module length in patterns */
169 int rst; /* Restart position */
170 int gvl; /* Global volume */
172 struct xmp_pattern **xxp; /* Patterns */
173 struct xmp_track **xxt; /* Tracks */
174 struct xmp_instrument *xxi; /* Instruments */
175 struct xmp_sample *xxs; /* Samples */
176 struct xmp_channel xxc[64]; /* Channel info */
177 unsigned char xxo[XMP_MAX_MOD_LENGTH]; /* Orders */
180 //struct xmp_test_info {
181 // char name[XMP_NAME_SIZE]; /* Module title */
182 // char type[XMP_NAME_SIZE]; /* Module format */
185 struct xmp_module_info {
186 unsigned char md5[16]; /* MD5 message digest */
187 int vol_base; /* Volume scale */
188 struct xmp_module *mod; /* Pointer to module data */
189 char *comment; /* Comment text, if any */
190 int num_sequences; /* Number of valid sequences */
191 struct xmp_sequence *seq_data; /* Pointer to sequence data */
194 struct xmp_frame_info
195 // { /* Current frame information */
196 // int pos; /* Current position */
197 // int pattern; /* Current pattern */
198 // int row; /* Current row in pattern */
199 // int num_rows; /* Number of rows in current pattern */
200 // int frame; /* Current frame */
201 // int speed; /* Current replay speed */
202 // int bpm; /* Current bpm */
203 // int time; /* Current module time in ms */
204 // int total_time; /* Estimated replay time in ms*/
205 // int frame_time; /* Frame replay time in us */
206 // void *buffer; /* Pointer to sound buffer */
207 // int buffer_size; /* Used buffer size */
208 // int total_size; /* Total buffer size */
209 // int volume; /* Current master volume */
210 // int loop_count; /* Loop counter */
211 // int virt_channels; /* Number of virtual channels */
212 // int virt_used; /* Used virtual channels */
213 // int sequence; /* Current sequence */
215 // struct xmp_channel_info { /* Current channel information */
216 // unsigned int period; /* Sample period */
217 // unsigned int position; /* Sample position */
218 // short pitchbend; /* Linear bend from base note*/
219 // unsigned char note; /* Current base note number */
220 // unsigned char instrument; /* Current instrument number */
221 // unsigned char sample; /* Current sample number */
222 // unsigned char volume; /* Current volume */
223 // unsigned char pan; /* Current stereo pan */
224 // unsigned char reserved; /* Reserved */
225 // struct xmp_event event; /* Current track event */
226 // } channel_info[XMP_MAX_CHANNELS];
230 // Functions exported from libxmp
231 static xmp_context (*qxmp_create_context) (void);
232 static void (*qxmp_free_context) (xmp_context);
233 //static int (*qxmp_test_module) (char *, struct xmp_test_info *);
234 //static int (*qxmp_load_module) (xmp_context, char *);
235 //static void (*qxmp_scan_module) (xmp_context);
236 static void (*qxmp_release_module) (xmp_context);
237 static int (*qxmp_start_player) (xmp_context, int, int);
238 static int (*qxmp_play_frame) (xmp_context);
239 static int (*qxmp_play_buffer) (xmp_context, void *, int, int);
240 static void (*qxmp_get_frame_info) (xmp_context, struct xmp_frame_info *);
241 static void (*qxmp_end_player) (xmp_context);
242 //static void (*qxmp_inject_event) (xmp_context, int, struct xmp_event *);
243 static void (*qxmp_get_module_info) (xmp_context, struct xmp_module_info *);
244 //static char **(*qxmp_get_format_list) (void); // FIXME: did I do this right?
245 //static int (*qxmp_next_position) (xmp_context);
246 //static int (*qxmp_prev_position) (xmp_context);
247 //static int (*qxmp_set_position) (xmp_context, int);
248 //static void (*qxmp_stop_module) (xmp_context);
249 //static void (*qxmp_restart_module) (xmp_context);
250 //static int (*qxmp_seek_time) (xmp_context, int);
251 //static int (*qxmp_channel_mute) (xmp_context, int, int);
252 //static int (*qxmp_channel_vol) (xmp_context, int, int);
253 static int (*qxmp_set_player) (xmp_context, int, int);
254 static int (*qxmp_get_player) (xmp_context, int);
255 //static int (*qxmp_set_instrument_path) (xmp_context, char *);
256 static int (*qxmp_load_module_from_memory) (xmp_context, void *, long);
257 //static int (*qxmp_load_module_from_file) (xmp_context, void *, long);
258 //static int (XMP_EXPORT *qxmp_load_module_from_file) (xmp_context, void *, long);
260 /* External sample mixer API */
262 static int (*qxmp_start_smix) (xmp_context, int, int);
263 static void (*qxmp_end_smix) (xmp_context);
264 static int (*qxmp_smix_play_instrument)(xmp_context, int, int, int, int);
265 static int (*qxmp_smix_play_sample) (xmp_context, int, int, int, int);
266 static int (*qxmp_smix_channel_pan) (xmp_context, int, int);
267 static int (*qxmp_smix_load_sample) (xmp_context, int, char *);
268 static int (*qxmp_smix_release_sample) (xmp_context, int);
269 // end Functions exported from libxmp
273 =================================================================
275 DarkPlaces definitions
277 =================================================================
280 static dllfunction_t xmpfuncs[] =
283 // Version and player information
284 {"xmp_version", (void **) &qxmp_version},
285 {"xmp_vercode", (void **) &qxmp_vercode},
286 // {"xmp_get_format_list", (void **) &qxmp_get_format_list},
288 {"xmp_create_context", (void **) &qxmp_create_context},
289 {"xmp_free_context", (void **) &qxmp_free_context},
291 // {"xmp_test_module", (void **) &qxmp_test_module},
292 // {"xmp_load_module", (void **) &qxmp_load_module},
293 {"xmp_load_module_from_memory", (void **) &qxmp_load_module_from_memory}, // since libxmp 4.2.0
294 // {"xmp_load_module_from_file", (void **) &qxmp_load_module_from_file}, // since libxmp 4.3.0
295 {"xmp_release_module", (void **) &qxmp_release_module},
296 // {"xmp_scan_module", (void **) &qxmp_scan_module},
297 {"xmp_get_module_info", (void **) &qxmp_get_module_info},
299 {"xmp_start_player", (void **) &qxmp_start_player},
300 {"xmp_play_frame", (void **) &qxmp_play_frame},
301 {"xmp_play_buffer", (void **) &qxmp_play_buffer},
302 {"xmp_get_frame_info", (void **) &qxmp_get_frame_info},
303 {"xmp_end_player", (void **) &qxmp_end_player},
305 // {"xmp_next_position", (void **) &qxmp_next_position},
306 // {"xmp_prev_position", (void **) &qxmp_prev_position},
307 // {"xmp_set_position", (void **) &qxmp_set_position},
308 // {"xmp_stop_module", (void **) &qxmp_stop_module},
309 // {"xmp_restart_module", (void **) &qxmp_restart_module},
310 // {"xmp_seek_time", (void **) &qxmp_seek_time},
311 // {"xmp_channel_mute", (void **) &qxmp_channel_mute},
312 // {"xmp_channel_vol", (void **) &qxmp_channel_vol},
313 // {"xmp_inject_event", (void **) &qxmp_inject_event},
314 // Player parameter setting
315 // {"xmp_set_instrument_path", (void **) &qxmp_set_instrument_path},
316 {"xmp_get_player", (void **) &qxmp_get_player},
317 {"xmp_set_player", (void **) &qxmp_set_player},
318 /* smix */ // for completeness sake only, right now
319 // {"xmp_start_smix", (void **) &qxmp_start_smix},
320 // {"xmp_end_smix", (void **) &qxmp_end_smix},
321 // {"xmp_smix_play_instrument", (void **) &qxmp_smix_play_instrument},
322 // {"xmp_smix_play_sample", (void **) &qxmp_smix_play_sample},
323 // {"xmp_smix_channel_pan", (void **) &qxmp_smix_channel_pan},
324 // {"xmp_smix_load_sample", (void **) &qxmp_smix_load_sample},
325 // {"xmp_smix_release_sample", (void **) &qxmp_smix_release_sample},
330 static dllhandle_t xmp_dll = NULL;
334 =================================================================
338 =================================================================
345 Try to load the libxmp DLL
348 qboolean XMP_OpenLibrary (void)
350 const char* dllnames_xmp [] =
355 #elif defined(MACOSX) // FIXME: untested, please test a mac os build
365 if (xmp_dll) // Already loaded?
368 // COMMANDLINEOPTION: Sound: -noxmp disables xmp module sound support
369 if (COM_CheckParm("-noxmp"))
373 if (Sys_LoadLibrary (dllnames_xmp, &xmp_dll, xmpfuncs))
375 if (*qxmp_vercode < 0x040200)
377 Con_Printf("Found incompatible XMP library version %s, not loading. (4.2.0 or higher required)\n", *qxmp_version);
378 Sys_UnloadLibrary (&xmp_dll);
381 if (developer_loading.integer >= 1)
382 Con_Printf("XMP library loaded, version %s (0x0%x)\n", *qxmp_version, *qxmp_vercode);
394 Unload the libxmp DLL
397 void XMP_CloseLibrary (void)
399 Sys_UnloadLibrary (&xmp_dll);
405 =================================================================
409 =================================================================
412 // Per-sfx data structure
417 } xmp_stream_persfx_t;
419 // Per-channel data structure
422 xmp_context playercontext;
424 int buffer_firstframe;
425 int buffer_numframes;
426 unsigned char buffer[STREAM_BUFFERSIZE*4];
427 } xmp_stream_perchannel_t;
435 static void XMP_GetSamplesFloat(channel_t *ch, sfx_t *sfx, int firstsampleframe, int numsampleframes, float *outsamplesfloat)
437 int i, len = numsampleframes * sfx->format.channels;
438 int f = sfx->format.width * sfx->format.channels; // bytes per frame in the buffer
439 xmp_stream_perchannel_t* per_ch = (xmp_stream_perchannel_t *)ch->fetcher_data;
440 xmp_stream_persfx_t* per_sfx = (xmp_stream_persfx_t *)sfx->fetcher_data;
443 unsigned int format = 0;
445 // if this channel does not yet have a channel fetcher, make one
448 // allocate a struct to keep track of our file position and buffer
449 per_ch = (xmp_stream_perchannel_t *)Mem_Alloc(snd_mempool, sizeof(*per_ch));
451 // create an xmp file context
452 if ((per_ch->playercontext = qxmp_create_context()) == NULL)
454 //Con_Printf("error getting a libxmp file context; while trying to load file \"%s\"\n", filename);
459 if (qxmp_load_module_from_memory(per_ch->playercontext, (void *)per_sfx->file, (long)per_sfx->filesize) < 0)
461 qxmp_free_context(per_ch->playercontext);
466 // start playing the loaded file
467 if (sfx->format.width == 1) { format |= XMP_FORMAT_8BIT | XMP_FORMAT_UNSIGNED; } // else 16bit
468 if (sfx->format.channels == 1) { format |= XMP_FORMAT_MONO; } // else stereo
470 if (qxmp_start_player(per_ch->playercontext, sfx->format.speed, format) < 0)
475 /* percentual left/right channel separation, default is 70. */
476 if (sfx->format.channels == 2 && (qxmp_set_player(per_ch->playercontext, XMP_PLAYER_MIX, 50) != 0))
481 /* interpolation type, default is XMP_INTERP_LINEAR */
482 if (qxmp_set_player(per_ch->playercontext, XMP_PLAYER_INTERP, XMP_INTERP_SPLINE) != 0)
489 per_ch->buffer_firstframe = 0;
490 per_ch->buffer_numframes = 0;
491 // attach the struct to our channel
492 ch->fetcher_data = (void *)per_ch;
494 // reset internal xmp state / syncs buffer start with frame start
495 qxmp_play_buffer(per_ch->playercontext, NULL, 0, 0);
498 // if the request is too large for our buffer, loop...
499 while (numsampleframes * f > (int)sizeof(per_ch->buffer))
501 done = sizeof(per_ch->buffer) / f;
502 XMP_GetSamplesFloat(ch, sfx, firstsampleframe, done, outsamplesfloat);
503 firstsampleframe += done;
504 numsampleframes -= done;
505 outsamplesfloat += done * sfx->format.channels;
508 // seek if the request is before the current buffer (loop back)
509 // seek if the request starts beyond the current buffer by at least one frame (channel was zero volume for a while)
510 // do not seek if the request overlaps the buffer end at all (expected behavior)
511 if (per_ch->buffer_firstframe > firstsampleframe || per_ch->buffer_firstframe + per_ch->buffer_numframes < firstsampleframe)
513 // we expect to decode forward from here so this will be our new buffer start
514 per_ch->buffer_firstframe = firstsampleframe;
515 per_ch->buffer_numframes = 0;
516 // no seeking at this time
519 // render the file to pcm as needed
520 if (firstsampleframe + numsampleframes > per_ch->buffer_firstframe + per_ch->buffer_numframes)
522 // first slide the buffer back, discarding any data preceding the range we care about
523 int offset = firstsampleframe - per_ch->buffer_firstframe;
524 int keeplength = per_ch->buffer_numframes - offset;
526 memmove(per_ch->buffer, per_ch->buffer + offset * sfx->format.width * sfx->format.channels, keeplength * sfx->format.width * sfx->format.channels);
527 per_ch->buffer_firstframe = firstsampleframe;
528 per_ch->buffer_numframes -= offset;
529 // render as much as we can fit in the buffer
530 newlength = sizeof(per_ch->buffer) - per_ch->buffer_numframes * f;
532 // while (newlength > done && qxmp_play_buffer(per_ch->playercontext, (void *)((char *)per_ch->buffer + done), (int)(newlength - done), 1) == 0) // don't loop by default (TODO: fix pcm duration calculation first)
533 while (newlength > done && qxmp_play_buffer(per_ch->playercontext, (void *)((char *)per_ch->buffer + done), (int)(newlength - done), 0) == 0) // loop forever
535 done += (int)(newlength - done);
537 // clear the missing space if any
538 if (done < newlength)
540 memset(per_ch->buffer + done, 0, newlength - done);
542 // we now have more data in the buffer
543 per_ch->buffer_numframes += done / f;
546 // convert the sample format for the caller
547 buf = (short *)((char *)per_ch->buffer + (firstsampleframe - per_ch->buffer_firstframe) * f);
548 for (i = 0;i < len;i++)
549 outsamplesfloat[i] = buf[i] * (1.0f / 32768.0f);
557 static void XMP_StopChannel(channel_t *ch)
559 xmp_stream_perchannel_t *per_ch = (xmp_stream_perchannel_t *)ch->fetcher_data;
563 qxmp_end_player(per_ch->playercontext);
565 qxmp_release_module(per_ch->playercontext);
566 // free the xmp playercontext
567 qxmp_free_context(per_ch->playercontext);
577 static void XMP_FreeSfx(sfx_t *sfx)
579 xmp_stream_persfx_t* per_sfx = (xmp_stream_persfx_t *)sfx->fetcher_data;
580 // free the complete file we were keeping around
581 Mem_Free(per_sfx->file);
582 // free the file information structure
586 static const snd_fetcher_t xmp_fetcher = { XMP_GetSamplesFloat, XMP_StopChannel, XMP_FreeSfx };
592 Load an XMP module file into memory
595 qboolean XMP_LoadModFile(const char *filename, sfx_t *sfx)
597 fs_offset_t filesize;
600 xmp_stream_persfx_t* per_sfx;
601 struct xmp_module_info mi;
603 #ifndef LINK_TO_LIBXMP
608 // COMMANDLINEOPTION: Sound: -noxmp disables xmp module sound support
609 if (COM_CheckParm("-noxmp"))
612 // Return if already loaded
613 if (sfx->fetcher != NULL)
617 data = FS_LoadFile(filename, snd_mempool, false, &filesize);
621 // Create an xmp file context
622 if ((xc = qxmp_create_context()) == NULL)
624 Con_Printf("error creating a libxmp file context; while trying to load file \"%s\"\n", filename);
629 if (developer_loading.integer >= 2)
630 Con_Printf("Loading Module file (libxmp) \"%s\"\n", filename);
632 if (qxmp_load_module_from_memory(xc, (void *)data, (long)filesize) < 0) // Added in libxmp 4.2
634 Con_Printf("error while trying to load xmp module \"%s\"\n", filename);
635 qxmp_free_context(xc);
640 if (developer_loading.integer >= 2)
641 Con_Printf ("\"%s\" will be streamed\n", filename);
643 // keep the file around
644 per_sfx = (xmp_stream_persfx_t *)Mem_Alloc (snd_mempool, sizeof (*per_sfx));
645 per_sfx->file = data;
646 per_sfx->filesize = filesize;
648 sfx->memsize += sizeof(*per_sfx);
649 sfx->memsize += filesize; // total memory used (including sfx_t and fetcher data)
650 if (S_GetSoundRate() > XMP_MAX_SRATE)
651 sfx->format.speed = 48000;
652 else if (S_GetSoundRate() < XMP_MIN_SRATE)
653 sfx->format.speed = 8000;
655 sfx->format.speed = S_GetSoundRate();
656 sfx->format.width = S_GetSoundWidth(); // 2 = 16 bit samples
657 sfx->format.channels = S_GetSoundChannels();
658 sfx->flags |= SFXFLAG_STREAMED; // cf SFXFLAG_* defines
659 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!)
660 sfx->loopstart = sfx->total_length; // (modplug does it) in sample frames. equals total_length if not looped
661 sfx->fetcher_data = per_sfx;
662 sfx->fetcher = &xmp_fetcher;
663 sfx->volume_peak = 0;
665 qxmp_get_module_info(xc, &mi);
666 if (developer_loading.integer >= 2)
668 Con_Printf("Decoding module (libxmp):\n"
669 " Module name : %s\n"
670 " Module type : %s\n"
671 " Module length: %i patterns\n"
673 " Instruments : %i\n"
676 " Initial Speed: %i\n"
677 " Initial BPM : %i\n"
678 " Restart Pos. : %i\n"
679 " Global Volume: %i\n",
680 mi.mod->name, mi.mod->type,
681 mi.mod->len, mi.mod->pat, mi.mod->ins, mi.mod->smp, mi.mod->chn,
682 mi.mod->spd, mi.mod->bpm, mi.mod->rst, mi.mod->gvl
685 else if (developer_loading.integer == 1)
686 Con_Printf("Decoding module (libxmp) \"%s\" (%s)\n", mi.mod->name, mi.mod->type);
688 qxmp_free_context(xc);