2 Copyright (C) 2003-2005 Mathieu Olivier
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, write to:
18 Free Software Foundation, Inc.
19 59 Temple Place - Suite 330
20 Boston, MA 02111-1307, USA
27 #include "snd_modplug.h"
29 #ifdef LINK_TO_LIBMODPLUG
31 #include <libmodplug/modplug.h>
32 qboolean ModPlug_OpenLibrary (void)
34 return true; // statically linked
36 void ModPlug_CloseLibrary (void)
40 #define qModPlug_Load ModPlug_Load
41 #define qModPlug_Unload ModPlug_Unload
42 #define qModPlug_Read ModPlug_Read
43 #define qModPlug_Seek ModPlug_Seek
44 #define qModPlug_GetSettings ModPlug_GetSettings
45 #define qModPlug_SetSettings ModPlug_SetSettings
46 #define qModPlug_SetMasterVolume ModPlug_SetMasterVolume
49 // BEGIN SECTION FROM modplug.h
52 * This source code is public domain.
54 * Authors: Kenton Varda <temporal@gauge3d.org> (C interface wrapper)
59 MODPLUG_ENABLE_OVERSAMPLING = 1 << 0, /* Enable oversampling (*highly* recommended) */
60 MODPLUG_ENABLE_NOISE_REDUCTION = 1 << 1, /* Enable noise reduction */
61 MODPLUG_ENABLE_REVERB = 1 << 2, /* Enable reverb */
62 MODPLUG_ENABLE_MEGABASS = 1 << 3, /* Enable megabass */
63 MODPLUG_ENABLE_SURROUND = 1 << 4 /* Enable surround sound. */
66 enum _ModPlug_ResamplingMode
68 MODPLUG_RESAMPLE_NEAREST = 0, /* No interpolation (very fast, extremely bad sound quality) */
69 MODPLUG_RESAMPLE_LINEAR = 1, /* Linear interpolation (fast, good quality) */
70 MODPLUG_RESAMPLE_SPLINE = 2, /* Cubic spline interpolation (high quality) */
71 MODPLUG_RESAMPLE_FIR = 3 /* 8-tap fir filter (extremely high quality) */
74 typedef struct _ModPlug_Settings
76 int mFlags; /* One or more of the MODPLUG_ENABLE_* flags above, bitwise-OR'ed */
78 /* Note that ModPlug always decodes sound at 44100kHz, 32 bit, stereo and then
79 * down-mixes to the settings you choose. */
80 int mChannels; /* Number of channels - 1 for mono or 2 for stereo */
81 int mBits; /* Bits per sample - 8, 16, or 32 */
82 int mFrequency; /* Sampling rate - 11025, 22050, or 44100 */
83 int mResamplingMode; /* One of MODPLUG_RESAMPLE_*, above */
85 int mStereoSeparation; /* Stereo separation, 1 - 256 */
86 int mMaxMixChannels; /* Maximum number of mixing channels (polyphony), 32 - 256 */
88 int mReverbDepth; /* Reverb level 0(quiet)-100(loud) */
89 int mReverbDelay; /* Reverb delay in ms, usually 40-200ms */
90 int mBassAmount; /* XBass level 0(quiet)-100(loud) */
91 int mBassRange; /* XBass cutoff in Hz 10-100 */
92 int mSurroundDepth; /* Surround level 0(quiet)-100(heavy) */
93 int mSurroundDelay; /* Surround delay in ms, usually 5-40ms */
94 int mLoopCount; /* Number of times to loop. Zero prevents looping.
99 typedef struct _ModPlugFile ModPlugFile;
101 // END SECTION FROM modplug.h
103 static ModPlugFile* (*qModPlug_Load) (const void* data, int size);
104 static void (*qModPlug_Unload) (ModPlugFile* file);
105 static int (*qModPlug_Read) (ModPlugFile* file, void* buffer, int size);
106 static void (*qModPlug_Seek) (ModPlugFile* file, int millisecond);
107 static void (*qModPlug_GetSettings) (ModPlug_Settings* settings);
108 static void (*qModPlug_SetSettings) (const ModPlug_Settings* settings);
109 typedef void (ModPlug_SetMasterVolume_t) (ModPlugFile* file,unsigned int cvol) ;
110 ModPlug_SetMasterVolume_t *qModPlug_SetMasterVolume;
113 static dllfunction_t modplugfuncs[] =
115 {"ModPlug_Load", (void **) &qModPlug_Load},
116 {"ModPlug_Unload", (void **) &qModPlug_Unload},
117 {"ModPlug_Read", (void **) &qModPlug_Read},
118 {"ModPlug_Seek", (void **) &qModPlug_Seek},
119 {"ModPlug_GetSettings", (void **) &qModPlug_GetSettings},
120 {"ModPlug_SetSettings", (void **) &qModPlug_SetSettings},
124 // Handles for the modplug and modplugfile DLLs
125 static dllhandle_t modplug_dll = NULL;
128 =================================================================
132 =================================================================
139 Try to load the modplugFile DLL
142 qboolean ModPlug_OpenLibrary (void)
144 const char* dllnames_modplug [] =
149 #elif defined(MACOSX)
162 // COMMANDLINEOPTION: Sound: -nomodplug disables modplug sound support
163 if (COM_CheckParm("-nomodplug"))
167 Con_Print("Warning: no modplug support in Android yet.\n");
172 // We need to load both by hand because some OSes seem to not load
173 // the modplug DLL automatically when loading the modplugFile DLL
174 if(Sys_LoadLibrary (dllnames_modplug, &modplug_dll, modplugfuncs))
176 qModPlug_SetMasterVolume = (ModPlug_SetMasterVolume_t *) Sys_GetProcAddress(modplug_dll, "ModPlug_SetMasterVolume");
177 if(!qModPlug_SetMasterVolume)
178 Con_Print("Warning: modplug volume control not supported. Try getting a newer version of libmodplug.\n");
190 Unload the modplugFile DLL
193 void ModPlug_CloseLibrary (void)
195 Sys_UnloadLibrary (&modplug_dll);
201 =================================================================
205 =================================================================
208 // Per-sfx data structure
213 } modplug_stream_persfx_t;
215 // Per-channel data structure
220 int buffer_firstframe;
221 int buffer_numframes;
222 unsigned char buffer[STREAM_BUFFERSIZE*4];
223 } modplug_stream_perchannel_t;
228 ModPlug_GetSamplesFloat
231 static void ModPlug_GetSamplesFloat(channel_t *ch, sfx_t *sfx, int firstsampleframe, int numsampleframes, float *outsamplesfloat)
233 modplug_stream_perchannel_t* per_ch = (modplug_stream_perchannel_t *)ch->fetcher_data;
234 modplug_stream_persfx_t* per_sfx = (modplug_stream_persfx_t *)sfx->fetcher_data;
235 int newlength, done, ret;
236 int f = sfx->format.width * sfx->format.channels; // bytes per frame
240 // If there's no fetcher structure attached to the channel yet
243 per_ch = (modplug_stream_perchannel_t *)Mem_Alloc(snd_mempool, sizeof(*per_ch));
245 // Open it with the modplugFile API
246 per_ch->mf = qModPlug_Load(per_sfx->file, per_sfx->filesize);
249 // we can't call Con_Printf here, not thread safe
250 // Con_Printf("error while reading ModPlug stream \"%s\"\n", per_sfx->name);
255 #ifndef LINK_TO_LIBMODPLUG
256 if(qModPlug_SetMasterVolume)
258 qModPlug_SetMasterVolume(per_ch->mf, 512); // max volume, DP scales down!
262 per_ch->buffer_firstframe = 0;
263 per_ch->buffer_numframes = 0;
264 ch->fetcher_data = per_ch;
267 // if the request is too large for our buffer, loop...
268 while (numsampleframes * f > (int)sizeof(per_ch->buffer))
270 done = sizeof(per_ch->buffer) / f;
271 ModPlug_GetSamplesFloat(ch, sfx, firstsampleframe, done, outsamplesfloat);
272 firstsampleframe += done;
273 numsampleframes -= done;
274 outsamplesfloat += done * sfx->format.channels;
277 // seek if the request is before the current buffer (loop back)
278 // seek if the request starts beyond the current buffer by at least one frame (channel was zero volume for a while)
279 // do not seek if the request overlaps the buffer end at all (expected behavior)
280 if (per_ch->buffer_firstframe > firstsampleframe || per_ch->buffer_firstframe + per_ch->buffer_numframes < firstsampleframe)
282 // we expect to decode forward from here so this will be our new buffer start
283 per_ch->buffer_firstframe = firstsampleframe;
284 per_ch->buffer_numframes = 0;
285 // we don't actually seek - we don't care much about timing on silent mod music streams and looping never happens
286 //qModPlug_Seek(per_ch->mf, firstsampleframe * 1000.0 / sfx->format.speed);
289 // decompress the file as needed
290 if (firstsampleframe + numsampleframes > per_ch->buffer_firstframe + per_ch->buffer_numframes)
292 // first slide the buffer back, discarding any data preceding the range we care about
293 int offset = firstsampleframe - per_ch->buffer_firstframe;
294 int keeplength = per_ch->buffer_numframes - offset;
296 memmove(per_ch->buffer, per_ch->buffer + offset * sfx->format.width * sfx->format.channels, keeplength * sfx->format.width * sfx->format.channels);
297 per_ch->buffer_firstframe = firstsampleframe;
298 per_ch->buffer_numframes -= offset;
299 // decompress as much as we can fit in the buffer
300 newlength = sizeof(per_ch->buffer) - per_ch->buffer_numframes * f;
302 while (newlength > done && (ret = qModPlug_Read(per_ch->mf, (void *)((unsigned char *)per_ch->buffer + done), (int)(newlength - done))) > 0)
304 // clear the missing space if any
305 if (done < newlength)
307 memset(per_ch->buffer + done, 0, newlength - done);
308 // Argh. We didn't get as many samples as we wanted. Probably
309 // libmodplug forgot what mLoopCount==-1 means... basically, this means
310 // we can't loop like this. Try to let DP fix it later...
311 sfx->total_length = firstsampleframe + done / f;
313 // can't Con_Printf from this thread
314 //if (newlength != done)
315 // Con_DPrintf("ModPlug_Fetch: wanted: %d, got: %d\n", newlength, done);
317 // we now have more data in the buffer
318 per_ch->buffer_numframes += done / f;
321 // convert the sample format for the caller
322 buf = (short *)(per_ch->buffer + (firstsampleframe - per_ch->buffer_firstframe) * f);
323 len = numsampleframes * sfx->format.channels;
324 for (i = 0;i < len;i++)
325 outsamplesfloat[i] = buf[i] * (1.0f / 32768.0f);
334 static void ModPlug_StopChannel(channel_t *ch)
336 modplug_stream_perchannel_t *per_ch = (modplug_stream_perchannel_t *)ch->fetcher_data;
340 // Free the modplug decoder
341 qModPlug_Unload(per_ch->mf);
353 static void ModPlug_FreeSfx (sfx_t *sfx)
355 modplug_stream_persfx_t* per_sfx = (modplug_stream_persfx_t *)sfx->fetcher_data;
357 // Free the modplug file
358 Mem_Free(per_sfx->file);
360 // Free the stream structure
365 static const snd_fetcher_t modplug_fetcher = { ModPlug_GetSamplesFloat, ModPlug_StopChannel, ModPlug_FreeSfx };
370 ModPlug_LoadmodplugFile
372 Load an modplug file into memory
375 qboolean ModPlug_LoadModPlugFile (const char *filename, sfx_t *sfx)
378 fs_offset_t filesize;
380 modplug_stream_persfx_t* per_sfx;
387 if (sfx->fetcher != NULL)
391 data = FS_LoadFile (filename, snd_mempool, false, &filesize);
395 if (developer_loading.integer >= 2)
396 Con_Printf ("Loading ModPlug file \"%s\"\n", filename);
398 qModPlug_GetSettings(&s);
399 s.mFlags = MODPLUG_ENABLE_OVERSAMPLING | MODPLUG_ENABLE_NOISE_REDUCTION | MODPLUG_ENABLE_REVERB;
402 s.mFrequency = 44100;
403 s.mResamplingMode = MODPLUG_RESAMPLE_SPLINE;
405 qModPlug_SetSettings(&s);
407 // Open it with the modplugFile API
408 if (!(mf = qModPlug_Load (data, filesize)))
410 Con_Printf ("error while opening ModPlug file \"%s\"\n", filename);
415 #ifndef LINK_TO_LIBMODPLUG
416 if(qModPlug_SetMasterVolume)
418 qModPlug_SetMasterVolume(mf, 512); // max volume, DP scales down!
420 if (developer_loading.integer >= 2)
421 Con_Printf ("\"%s\" will be streamed\n", filename);
422 per_sfx = (modplug_stream_persfx_t *)Mem_Alloc (snd_mempool, sizeof (*per_sfx));
423 per_sfx->file = data;
424 per_sfx->filesize = filesize;
425 sfx->memsize += sizeof(*per_sfx);
426 sfx->memsize += filesize;
427 sfx->format.speed = 44100; // modplug always works at that rate
428 sfx->format.width = 2; // We always work with 16 bits samples
429 sfx->format.channels = 2; // stereo rulez ;) (MAYBE default to mono because Amiga MODs sound better then?)
430 sfx->fetcher_data = per_sfx;
431 sfx->fetcher = &modplug_fetcher;
432 sfx->flags |= SFXFLAG_STREAMED;
433 sfx->total_length = 1<<30; // 2147384647; // they always loop (FIXME this breaks after 6 hours, we need support for a real "infinite" value!)
434 sfx->loopstart = sfx->total_length; // modplug does it