Skip to content

Commit

Permalink
Moved all the global ModPlug state into the CSoundFile struct.
Browse files Browse the repository at this point in the history
This means that each decoded thing doesn't have to share state, so we can
ditch our mutex and tapdancing to only change settings when there are no
other sounds decoding.
  • Loading branch information
icculus committed Jul 20, 2018
1 parent c9b57b1 commit 940142c
Show file tree
Hide file tree
Showing 15 changed files with 461 additions and 630 deletions.
139 changes: 34 additions & 105 deletions src/SDL_sound_modplug.c
Expand Up @@ -83,57 +83,15 @@ const Sound_DecoderFunctions __Sound_DecoderFunctions_MODPLUG =
};


static ModPlug_Settings settings;
static Sound_AudioInfo current_audioinfo;
static unsigned int total_mods_decoding = 0;
static SDL_mutex *modplug_mutex = NULL;

static int MODPLUG_init(void)
{
SDL_assert(modplug_mutex == NULL);

/*
* The settings will require some experimenting. I've borrowed some
* of them from the XMMS ModPlug plugin.
*/
settings.mFlags = MODPLUG_ENABLE_OVERSAMPLING;
settings.mFlags |= MODPLUG_ENABLE_NOISE_REDUCTION |
MODPLUG_ENABLE_MEGABASS |
MODPLUG_ENABLE_SURROUND;

settings.mReverbDepth = 30;
settings.mReverbDelay = 100;
settings.mBassAmount = 40;
settings.mBassRange = 30;
settings.mSurroundDepth = 20;
settings.mSurroundDelay = 20;
settings.mChannels = 2;
settings.mBits = 16;
settings.mFrequency = 44100;
settings.mResamplingMode = MODPLUG_RESAMPLE_FIR;
settings.mLoopCount = 0;

current_audioinfo.channels = 2;
current_audioinfo.rate = 44100;
current_audioinfo.format = AUDIO_S16SYS;
total_mods_decoding = 0;

modplug_mutex = SDL_CreateMutex();

ModPlug_SetSettings(&settings);
return 1; /* success. */
return ModPlug_Init(); /* success. */
} /* MODPLUG_init */


static void MODPLUG_quit(void)
{
SDL_assert(total_mods_decoding == 0);

if (modplug_mutex != NULL)
{
SDL_DestroyMutex(modplug_mutex);
modplug_mutex = NULL;
} /* if */
/* it's a no-op. */
} /* MODPLUG_quit */


Expand All @@ -145,6 +103,7 @@ static void MODPLUG_quit(void)

static int MODPLUG_open(Sound_Sample *sample, const char *ext)
{
ModPlug_Settings settings;
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
ModPlugFile *module;
Uint8 *data;
Expand Down Expand Up @@ -172,10 +131,8 @@ static int MODPLUG_open(Sound_Sample *sample, const char *ext)
BAIL_MACRO("MODPLUG: Not a module file.", 0);
} /* if */

/*
* ModPlug needs the entire stream in one big chunk. I don't like it,
* but I don't think there's any way around it.
*/
/* ModPlug needs the entire stream in one big chunk. I don't like it,
but I don't think there's any way around it. !!! FIXME: rework modplug? */
data = (Uint8 *) SDL_malloc(CHUNK_SIZE);
BAIL_IF_MACRO(data == NULL, ERR_OUT_OF_MEMORY, 0);
size = 0;
Expand All @@ -191,54 +148,39 @@ static int MODPLUG_open(Sound_Sample *sample, const char *ext)
} /* if */
} while (retval > 0);

/*
* It's only safe to change these settings when there're
* no other mods being decoded...
*/
if (modplug_mutex != NULL)
SDL_LockMutex(modplug_mutex);
SDL_memcpy(&sample->actual, &sample->desired, sizeof (Sound_AudioInfo));
if (sample->actual.rate == 0) sample->actual.rate = 44100;
if (sample->actual.channels == 0) sample->actual.channels = 2;
if (sample->actual.format == 0) sample->actual.format = AUDIO_S16SYS;

if (total_mods_decoding > 0)
{
/* other mods decoding: use the same settings they are. */
SDL_memcpy(&sample->actual, &current_audioinfo, sizeof (Sound_AudioInfo));
} /* if */
else
{
/* no other mods decoding: define the new ModPlug output settings. */
SDL_memcpy(&sample->actual, &sample->desired, sizeof (Sound_AudioInfo));
if (sample->actual.rate == 0)
sample->actual.rate = 44100;
if (sample->actual.channels == 0)
sample->actual.channels = 2;
if (sample->actual.format == 0)
sample->actual.format = AUDIO_S16SYS;

SDL_memcpy(&current_audioinfo, &sample->actual, sizeof (Sound_AudioInfo));
settings.mChannels=sample->actual.channels;
settings.mFrequency=sample->actual.rate;
settings.mBits = sample->actual.format & 0xFF;
ModPlug_SetSettings(&settings);
} /* else */

/*
* The buffer may be a bit too large, but that doesn't matter. I think
* it's safe to free it as soon as ModPlug_Load() is finished anyway.
*/
module = ModPlug_Load((void *) data, size);
SDL_free(data);
if (module == NULL)
{
if (modplug_mutex != NULL)
SDL_UnlockMutex(modplug_mutex);
settings.mChannels=sample->actual.channels;
settings.mFrequency=sample->actual.rate;
settings.mBits = sample->actual.format & 0xFF;

BAIL_MACRO("MODPLUG: Not a module file.", 0);
} /* if */
/* The settings will require some experimenting. I've borrowed some
of them from the XMMS ModPlug plugin. */
settings.mFlags = MODPLUG_ENABLE_OVERSAMPLING;
settings.mFlags |= MODPLUG_ENABLE_NOISE_REDUCTION |
MODPLUG_ENABLE_MEGABASS |
MODPLUG_ENABLE_SURROUND;

total_mods_decoding++;
settings.mReverbDepth = 30;
settings.mReverbDelay = 100;
settings.mBassAmount = 40;
settings.mBassRange = 30;
settings.mSurroundDepth = 20;
settings.mSurroundDelay = 20;
settings.mChannels = 2;
settings.mBits = 16;
settings.mFrequency = 44100;
settings.mResamplingMode = MODPLUG_RESAMPLE_FIR;
settings.mLoopCount = 0;

if (modplug_mutex != NULL)
SDL_UnlockMutex(modplug_mutex);
/* The buffer may be a bit too large, but that doesn't matter. I think
it's safe to free it as soon as ModPlug_Load() is finished anyway. */
module = ModPlug_Load((void *) data, size, &settings);
SDL_free(data);
BAIL_IF_MACRO(module == NULL, "MODPLUG: Not a module file.", 0);

internal->total_time = ModPlug_GetLength(module);
internal->decoder_private = (void *) module;
Expand All @@ -253,15 +195,6 @@ static void MODPLUG_close(Sound_Sample *sample)
{
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
ModPlugFile *module = (ModPlugFile *) internal->decoder_private;

if (modplug_mutex != NULL)
SDL_LockMutex(modplug_mutex);

total_mods_decoding--;

if (modplug_mutex != NULL)
SDL_UnlockMutex(modplug_mutex);

ModPlug_Unload(module);
} /* MODPLUG_close */

Expand All @@ -271,7 +204,6 @@ static Uint32 MODPLUG_read(Sound_Sample *sample)
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
ModPlugFile *module = (ModPlugFile *) internal->decoder_private;
int retval;

retval = ModPlug_Read(module, internal->buffer, internal->buffer_size);
if (retval == 0)
sample->flags |= SOUND_SAMPLEFLAG_EOF;
Expand All @@ -283,7 +215,6 @@ static int MODPLUG_rewind(Sound_Sample *sample)
{
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
ModPlugFile *module = (ModPlugFile *) internal->decoder_private;

ModPlug_Seek(module, 0);
return 1;
} /* MODPLUG_rewind */
Expand All @@ -293,8 +224,6 @@ static int MODPLUG_seek(Sound_Sample *sample, Uint32 ms)
{
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
ModPlugFile *module = (ModPlugFile *) internal->decoder_private;

/* Assume that this will work. */
ModPlug_Seek(module, ms);
return 1;
} /* MODPLUG_seek */
Expand Down
47 changes: 13 additions & 34 deletions src/libmodplug/fastmix.c
Expand Up @@ -8,23 +8,6 @@
#include "libmodplug.h"
#include <math.h>

// Front Mix Buffer (Also room for interleaved rear mix)
int MixSoundBuffer[MIXBUFFERSIZE*4];

// Reverb Mix Buffer
#ifndef MODPLUG_NO_REVERB
int MixReverbBuffer[MIXBUFFERSIZE*2];
extern UINT gnReverbSend;
#endif

int MixRearBuffer[MIXBUFFERSIZE*2];
float MixFloatBuffer[MIXBUFFERSIZE*2];

extern LONG gnDryROfsVol;
extern LONG gnDryLOfsVol;
extern LONG gnRvbROfsVol;
extern LONG gnRvbLOfsVol;

// 4x256 taps polyphase FIR resampling filter
extern short int gFastSinc[];
extern short int gKaiserSinc[]; // 8-taps polyphase
Expand Down Expand Up @@ -1450,7 +1433,7 @@ UINT CSoundFile_CreateStereoMix(CSoundFile *_this, int count)
UINT nrampsamples;

if (!count) return 0;
if (CSoundFile_gnChannels > 2) X86_InitMixBuffer(MixRearBuffer, count*2);
if (_this->gnChannels > 2) X86_InitMixBuffer(_this->MixRearBuffer, count*2);
nchused = nchmixed = 0;
for (UINT nChn=0; nChn<_this->m_nMixChannels; nChn++)
{
Expand All @@ -1463,8 +1446,8 @@ UINT CSoundFile_CreateStereoMix(CSoundFile *_this, int count)

if (!pChannel->pCurrentSample) continue;
nMasterCh = (_this->ChnMix[nChn] < _this->m_nChannels) ? _this->ChnMix[nChn]+1 : pChannel->nMasterChn;
pOfsR = &gnDryROfsVol;
pOfsL = &gnDryLOfsVol;
pOfsR = &_this->gnDryROfsVol;
pOfsL = &_this->gnDryLOfsVol;
nFlags = 0;
if (pChannel->dwFlags & CHN_16BIT) nFlags |= MIXNDX_16BIT;
if (pChannel->dwFlags & CHN_STEREO) nFlags |= MIXNDX_STEREO;
Expand All @@ -1474,10 +1457,10 @@ UINT CSoundFile_CreateStereoMix(CSoundFile *_this, int count)
if (!(pChannel->dwFlags & CHN_NOIDO))
{
// use hq-fir mixer?
if( (CSoundFile_gdwSoundSetup & (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE)) ==
if( (_this->gdwSoundSetup & (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE)) ==
(SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE) )
nFlags += MIXNDX_FIRSRC;
else if( (CSoundFile_gdwSoundSetup & (SNDMIX_HQRESAMPLER)) == SNDMIX_HQRESAMPLER )
else if( (_this->gdwSoundSetup & (SNDMIX_HQRESAMPLER)) == SNDMIX_HQRESAMPLER )
nFlags += MIXNDX_SPLINESRC;
else
nFlags += MIXNDX_LINEARSRC; // use
Expand All @@ -1492,16 +1475,16 @@ UINT CSoundFile_CreateStereoMix(CSoundFile *_this, int count)
}
nsamples = count;
#ifndef MODPLUG_NO_REVERB
pbuffer = (CSoundFile_gdwSoundSetup & SNDMIX_REVERB) ? MixReverbBuffer : MixSoundBuffer;
if (pChannel->dwFlags & CHN_NOREVERB) pbuffer = MixSoundBuffer;
if (pChannel->dwFlags & CHN_REVERB) pbuffer = MixReverbBuffer;
if (pbuffer == MixReverbBuffer)
pbuffer = (_this->gdwSoundSetup & SNDMIX_REVERB) ? _this->MixReverbBuffer : _this->MixSoundBuffer;
if (pChannel->dwFlags & CHN_NOREVERB) pbuffer = _this->MixSoundBuffer;
if (pChannel->dwFlags & CHN_REVERB) pbuffer = _this->MixReverbBuffer;
if (pbuffer == _this->MixReverbBuffer)
{
if (!gnReverbSend) SDL_memset(MixReverbBuffer, 0, count * 8);
gnReverbSend += count;
if (!_this->gnReverbSend) SDL_memset(_this->MixReverbBuffer, 0, count * 8);
_this->gnReverbSend += count;
}
#else
pbuffer = MixSoundBuffer;
pbuffer = _this->MixSoundBuffer;
#endif
nchused++;
////////////////////////////////////////////////////
Expand All @@ -1528,7 +1511,7 @@ UINT CSoundFile_CreateStereoMix(CSoundFile *_this, int count)
}
// Should we mix this channel ?
UINT naddmix;
if (((nchmixed >= CSoundFile_m_nMaxMixChannels) && (!(CSoundFile_gdwSoundSetup & SNDMIX_DIRECTTODISK)))
if (((nchmixed >= _this->m_nMaxMixChannels) && (!(_this->gdwSoundSetup & SNDMIX_DIRECTTODISK)))
|| ((!pChannel->nRampLength) && (!(pChannel->nLeftVol|pChannel->nRightVol))))
{
LONG delta = (pChannel->nInc * (LONG)nSmpCount) + (LONG)pChannel->nPosLo;
Expand Down Expand Up @@ -1715,10 +1698,6 @@ VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples)
}
}

#define OFSDECAYSHIFT 8
#define OFSDECAYMASK 0xFF


//---GCCFIX: Asm replaced with C function
#define OFSDECAYSHIFT 8
#define OFSDECAYMASK 0xFF
Expand Down

0 comments on commit 940142c

Please sign in to comment.