Audiolib housekeeping

git-svn-id: https://svn.eduke32.com/eduke32@7918 1a8010ca-5511-0410-912e-c29ae57300e0

# Conflicts:
#	source/audiolib/src/multivoc.cpp
This commit is contained in:
terminx 2019-08-07 22:44:41 +00:00 committed by Christoph Oelckers
parent 9302e48cef
commit 635a929359
3 changed files with 93 additions and 112 deletions

View file

@ -96,7 +96,7 @@ private:
}; };
#define MV_MIXBUFFERSIZE 256 #define MV_MIXBUFFERSIZE 256
#define MV_NUMBEROFBUFFERS 16 #define MV_NUMBEROFBUFFERS 32
#define MV_TOTALBUFFERSIZE ( MV_MIXBUFFERSIZE * MV_NUMBEROFBUFFERS ) #define MV_TOTALBUFFERSIZE ( MV_MIXBUFFERSIZE * MV_NUMBEROFBUFFERS )
typedef enum typedef enum

View file

@ -34,23 +34,23 @@
#define MIXBUFFERPOSITIONS 8 #define MIXBUFFERPOSITIONS 8
static int32_t ErrorCode = DSErr_Ok; static int32_t ErrorCode;
static int32_t Initialised; static int32_t Initialised;
static int32_t Playing; static int32_t Playing;
static char * MixBuffer = NULL; static char * MixBuffer;
static int32_t MixBufferSize; static int32_t MixBufferSize;
static int32_t MixBufferCount; static int32_t MixBufferCount;
static int32_t MixBufferCurrent; static int32_t MixBufferCurrent;
static int32_t MixBufferUsed; static int32_t MixBufferUsed;
static void (*MixCallBack)(void) = NULL; static void (*MixCallBack)(void);
static LPDIRECTSOUND lpds = NULL; static LPDIRECTSOUND lpds;
static LPDIRECTSOUNDBUFFER lpdsbprimary = NULL, lpdsbsec = NULL; static LPDIRECTSOUNDBUFFER lpdsbprimary, lpdsbsec;
static LPDIRECTSOUNDNOTIFY lpdsnotify = NULL; static LPDIRECTSOUNDNOTIFY lpdsnotify;
static HANDLE mixThread = NULL; static HANDLE mixThread;
static mutex_t mutex; static mutex_t mutex;
static DSBPOSITIONNOTIFY notifyPositions[MIXBUFFERPOSITIONS + 1] = {}; static DSBPOSITIONNOTIFY notifyPositions[MIXBUFFERPOSITIONS + 1] = {};

View file

@ -88,15 +88,15 @@ int32_t MV_ErrorCode = MV_NotInstalled;
float MV_GlobalVolume = 1.f; float MV_GlobalVolume = 1.f;
float MV_VolumeSmooth = 1.f; float MV_VolumeSmooth = 1.f;
static int32_t lockdepth = 0; static int lockdepth = 0;
void DisableInterrupts(void) static inline void MV_Lock(void)
{ {
if (!lockdepth++) if (!lockdepth++)
SoundDriver_Lock(); SoundDriver_Lock();
} }
void RestoreInterrupts(void) static inline void MV_Unlock(void)
{ {
if (!--lockdepth) if (!--lockdepth)
SoundDriver_Unlock(); SoundDriver_Unlock();
@ -104,100 +104,73 @@ void RestoreInterrupts(void)
MV_Printf("RestoreInterrupts(): lockdepth < 0!\n"); MV_Printf("RestoreInterrupts(): lockdepth < 0!\n");
} }
const char *MV_ErrorString(int32_t ErrorNumber) static bool MV_Mix(VoiceNode * const voice, int const buffer)
{
switch (ErrorNumber)
{
case MV_Error:
return MV_ErrorString(MV_ErrorCode);
case MV_Ok:
return "Multivoc ok.";
case MV_NotInstalled:
return "Multivoc not installed.";
case MV_DriverError:
return SoundDriver_ErrorString(SoundDriver_GetError());
case MV_NoVoices:
return "No free voices available to Multivoc.";
case MV_NoMem:
return "Out of memory in Multivoc.";
case MV_VoiceNotFound:
return "No voice with matching handle found.";
case MV_InvalidFile:
return "Invalid file passed in to Multivoc.";
default:
return "Unknown Multivoc error code.";
}
}
static bool MV_Mix(VoiceNode *voice, int const buffer)
{ {
/* cheap fix for a crash under 64-bit linux */ /* cheap fix for a crash under 64-bit linux */
/* v v v v */ /* v v v v */
if (voice->length == 0 && (voice->GetSound == NULL || voice->GetSound(voice) != KeepPlaying)) if (voice->length == 0 && (voice->GetSound == NULL || voice->GetSound(voice) != KeepPlaying))
return false; return false;
int32_t length = MV_MIXBUFFERSIZE; float const gv = MV_GlobalVolume;
uint32_t FixedPointBufferSize = voice->FixedPointBufferSize;
if (voice->priority == FX_MUSIC_PRIORITY)
MV_GlobalVolume = 1.f;
int32_t length = MV_MIXBUFFERSIZE;
uint32_t bufsiz = voice->FixedPointBufferSize;
uint32_t const rate = voice->RateScale;
MV_MixDestination = MV_MixBuffer[buffer]; MV_MixDestination = MV_MixBuffer[buffer];
// Add this voice to the mix // Add this voice to the mix
do do
{ {
uint32_t const rate = voice->RateScale; int32_t mixlen = length;
uint32_t const position = voice->position; uint32_t const position = voice->position;
int32_t voclength; uint32_t const voclen = voice->length;
// Check if the last sample in this buffer would be // Check if the last sample in this buffer would be
// beyond the length of the sample block // beyond the length of the sample block
if ((position + FixedPointBufferSize) >= voice->length) if ((position + bufsiz) >= voclen)
{ {
if (position >= voice->length) if (position >= voclen)
{ {
voice->GetSound(voice); voice->GetSound(voice);
return true; break;
} }
voclength = (voice->length - position + rate - voice->channels) / rate; mixlen = (voclen - position + rate - voice->channels) / rate;
} }
else
voclength = length;
float const gv = MV_GlobalVolume; voice->position = voice->mix(voice, mixlen);
length -= mixlen;
if (voice->priority == FX_MUSIC_PRIORITY) if (voice->position >= voclen)
MV_GlobalVolume = 1.f;
voice->position = voice->mix(voice, voclength);
MV_GlobalVolume = gv;
length -= voclength;
if (voice->position >= voice->length)
{ {
// Get the next block of sound // Get the next block of sound
if (voice->GetSound(voice) == NoMoreData) if (voice->GetSound(voice) == NoMoreData)
return false;
if (length > (voice->channels - 1))
{ {
// Get the position of the last sample in the buffer MV_GlobalVolume = gv;
FixedPointBufferSize = voice->RateScale * (length - voice->channels); return false;
} }
// Get the position of the last sample in the buffer
if (length > (voice->channels - 1))
bufsiz = voice->RateScale * (length - voice->channels);
} }
} while (length > 0); } while (length > 0);
MV_GlobalVolume = gv;
return true; return true;
} }
void MV_PlayVoice(VoiceNode *voice) void MV_PlayVoice(VoiceNode *voice)
{ {
DisableInterrupts(); MV_Lock();
LL::SortedInsert(&VoiceList, voice, &VoiceNode::priority); LL::SortedInsert(&VoiceList, voice, &VoiceNode::priority);
voice->LeftVolume = voice->LeftVolumeDest; voice->LeftVolume = voice->LeftVolumeDest;
voice->RightVolume = voice->RightVolumeDest; voice->RightVolume = voice->RightVolumeDest;
RestoreInterrupts(); MV_Unlock();
} }
static void MV_CleanupVoice(VoiceNode *voice) static void MV_CleanupVoice(VoiceNode *voice)
@ -225,12 +198,11 @@ static void MV_CleanupVoice(VoiceNode *voice)
static void MV_StopVoice(VoiceNode *voice) static void MV_StopVoice(VoiceNode *voice)
{ {
MV_Lock();
MV_CleanupVoice(voice); MV_CleanupVoice(voice);
DisableInterrupts();
// move the voice from the play list to the free list // move the voice from the play list to the free list
LL::Move(voice, &VoicePool); LL::Move(voice, &VoicePool);
RestoreInterrupts(); MV_Unlock();
} }
/*--------------------------------------------------------------------- /*---------------------------------------------------------------------
@ -243,15 +215,10 @@ static void MV_StopVoice(VoiceNode *voice)
static void MV_ServiceVoc(void) static void MV_ServiceVoc(void)
{ {
// Toggle which buffer we'll mix next // Toggle which buffer we'll mix next
if (++MV_MixPage >= MV_NumberOfBuffers) ++MV_MixPage &= MV_NumberOfBuffers-1;
MV_MixPage -= MV_NumberOfBuffers;
if (MV_ReverbLevel == 0) if (MV_ReverbLevel == 0)
{ {
// Initialize buffer
//Commented out so that the buffer is always cleared.
//This is so the guys at Echo Speech can mix into the
//buffer even when no sounds are playing.
if (!MV_BufferEmpty[MV_MixPage]) if (!MV_BufferEmpty[MV_MixPage])
{ {
Bmemset(MV_MixBuffer[MV_MixPage], 0, MV_BufferSize); Bmemset(MV_MixBuffer[MV_MixPage], 0, MV_BufferSize);
@ -260,48 +227,38 @@ static void MV_ServiceVoc(void)
} }
else else
{ {
char const *const end = MV_MixBuffer[0] + MV_BufferLength; char const *const end = MV_MixBuffer[0] + MV_BufferLength;
char *dest = MV_MixBuffer[MV_MixPage]; char * dest = MV_MixBuffer[MV_MixPage];
char const *source = MV_MixBuffer[MV_MixPage] - MV_ReverbDelay; char const * source = MV_MixBuffer[MV_MixPage] - MV_ReverbDelay;
if (source < MV_MixBuffer[ 0 ]) if (source < MV_MixBuffer[ 0 ])
source += MV_BufferLength; source += MV_BufferLength;
int32_t length = MV_BufferSize; int32_t length = MV_BufferSize;
while (length > 0) do
{ {
int const count = (source + length > end) ? (end - source) : length; int const count = (source + length > end) ? (end - source) : length;
MV_16BitReverb(source, dest, MV_ReverbVolume, count / 2); MV_16BitReverb(source, dest, MV_ReverbVolume, count >> 1);
// if we go through the loop again, it means that we've wrapped around the buffer // if we go through the loop again, it means that we've wrapped around the buffer
source = MV_MixBuffer[ 0 ]; source = MV_MixBuffer[ 0 ];
dest += count; dest += count;
length -= count; length -= count;
} } while (length > 0);
} }
// Play any waiting voices
//DisableInterrupts();
if (!VoiceList.next || VoiceList.next == &VoiceList) if (!VoiceList.next || VoiceList.next == &VoiceList)
return; return;
VoiceNode *voice = VoiceList.next; VoiceNode *voice = VoiceList.next;
int iter = 0;
VoiceNode *next; VoiceNode *next;
do do
{ {
next = voice->next; next = voice->next;
if (++iter > MV_MaxVoices && MV_Printf)
MV_Printf("more iterations than voices! iter: %d\n",iter);
if (voice->Paused) if (voice->Paused)
continue; continue;
@ -315,8 +272,6 @@ static void MV_ServiceVoc(void)
} }
} }
while ((voice = next) != &VoiceList); while ((voice = next) != &VoiceList);
//RestoreInterrupts();
} }
static VoiceNode *MV_GetVoice(int32_t handle) static VoiceNode *MV_GetVoice(int32_t handle)
@ -328,18 +283,18 @@ static VoiceNode *MV_GetVoice(int32_t handle)
return NULL; return NULL;
} }
DisableInterrupts(); MV_Lock();
for (VoiceNode *voice = VoiceList.next; voice != &VoiceList; voice = voice->next) for (VoiceNode *voice = VoiceList.next; voice != &VoiceList; voice = voice->next)
{ {
if (handle == voice->handle) if (handle == voice->handle)
{ {
RestoreInterrupts(); MV_Unlock();
return voice; return voice;
} }
} }
RestoreInterrupts(); MV_Unlock();
MV_SetErrorCode(MV_VoiceNotFound); MV_SetErrorCode(MV_VoiceNotFound);
return NULL; return NULL;
} }
@ -357,12 +312,12 @@ VoiceNode *MV_BeginService(int32_t handle)
return NULL; return NULL;
} }
DisableInterrupts(); MV_Lock();
return voice; return voice;
} }
static inline void MV_EndService(void) { RestoreInterrupts(); } static inline void MV_EndService(void) { MV_Unlock(); }
int32_t MV_VoicePlaying(int32_t handle) int32_t MV_VoicePlaying(int32_t handle)
{ {
@ -374,11 +329,11 @@ int32_t MV_KillAllVoices(void)
if (!MV_Installed) if (!MV_Installed)
return MV_Error; return MV_Error;
DisableInterrupts(); MV_Lock();
if (&VoiceList == VoiceList.next) if (&VoiceList == VoiceList.next)
{ {
RestoreInterrupts(); MV_Unlock();
return MV_Ok; return MV_Ok;
} }
@ -397,7 +352,7 @@ int32_t MV_KillAllVoices(void)
voice = VoiceList.prev; voice = VoiceList.prev;
} }
RestoreInterrupts(); MV_Unlock();
return MV_Ok; return MV_Ok;
} }
@ -420,14 +375,14 @@ int32_t MV_VoicesPlaying(void)
if (!MV_Installed) if (!MV_Installed)
return 0; return 0;
DisableInterrupts(); MV_Lock();
int NumVoices = 0; int NumVoices = 0;
for (VoiceNode *voice = VoiceList.next; voice != &VoiceList; voice = voice->next) for (VoiceNode *voice = VoiceList.next; voice != &VoiceList; voice = voice->next)
NumVoices++; NumVoices++;
RestoreInterrupts(); MV_Unlock();
return NumVoices; return NumVoices;
} }
@ -436,7 +391,7 @@ VoiceNode *MV_AllocVoice(int32_t priority)
{ {
VoiceNode *voice, *node; VoiceNode *voice, *node;
DisableInterrupts(); MV_Lock();
// Check if we have any free voices // Check if we have any free voices
if (LL::Empty(&VoicePool)) if (LL::Empty(&VoicePool))
@ -454,14 +409,14 @@ VoiceNode *MV_AllocVoice(int32_t priority)
if (LL::Empty(&VoicePool)) if (LL::Empty(&VoicePool))
{ {
// No free voices // No free voices
RestoreInterrupts(); MV_Unlock();
return NULL; return NULL;
} }
} }
voice = VoicePool.next; voice = VoicePool.next;
LL::Remove(voice); LL::Remove(voice);
RestoreInterrupts(); MV_Unlock();
int32_t vhan = MV_MINVOICEHANDLE; int32_t vhan = MV_MINVOICEHANDLE;
@ -483,7 +438,7 @@ int32_t MV_VoiceAvailable(int32_t priority)
if (!LL::Empty(&VoicePool)) if (!LL::Empty(&VoicePool))
return TRUE; return TRUE;
DisableInterrupts(); MV_Lock();
VoiceNode *voice, *node; VoiceNode *voice, *node;
@ -496,11 +451,11 @@ int32_t MV_VoiceAvailable(int32_t priority)
if ((voice == &VoiceList) || (priority < voice->priority)) if ((voice == &VoiceList) || (priority < voice->priority))
{ {
RestoreInterrupts(); MV_Unlock();
return FALSE; return FALSE;
} }
RestoreInterrupts(); MV_Unlock();
return TRUE; return TRUE;
} }
@ -563,7 +518,7 @@ int32_t MV_SetFrequency(int32_t handle, int32_t frequency)
void MV_SetVoiceMixMode(VoiceNode *voice) void MV_SetVoiceMixMode(VoiceNode *voice)
{ {
int32_t type = T_DEFAULT; int type = T_DEFAULT;
if (MV_Channels == 1) if (MV_Channels == 1)
type |= T_MONO; type |= T_MONO;
@ -717,7 +672,6 @@ void MV_SetReverb(int32_t reverb)
} }
int32_t MV_GetMaxReverbDelay(void) { return MV_MIXBUFFERSIZE * MV_NumberOfBuffers; } int32_t MV_GetMaxReverbDelay(void) { return MV_MIXBUFFERSIZE * MV_NumberOfBuffers; }
int32_t MV_GetReverbDelay(void) { return MV_ReverbDelay / MV_SampleSize; } int32_t MV_GetReverbDelay(void) { return MV_ReverbDelay / MV_SampleSize; }
void MV_SetReverbDelay(int32_t delay) void MV_SetReverbDelay(int32_t delay)
@ -735,6 +689,7 @@ static int32_t MV_SetMixMode(int32_t numchannels)
MV_BufferSize = MV_MIXBUFFERSIZE * MV_SampleSize; MV_BufferSize = MV_MIXBUFFERSIZE * MV_SampleSize;
MV_NumberOfBuffers = MV_TOTALBUFFERSIZE / MV_BufferSize; MV_NumberOfBuffers = MV_TOTALBUFFERSIZE / MV_BufferSize;
Bassert(isPow2(MV_NumberOfBuffers));
MV_BufferLength = MV_TOTALBUFFERSIZE; MV_BufferLength = MV_TOTALBUFFERSIZE;
MV_RightChannelOffset = MV_SampleSize >> 1; MV_RightChannelOffset = MV_SampleSize >> 1;
@ -766,7 +721,7 @@ static void MV_StopPlayback(void)
SoundDriver_StopPlayback(); SoundDriver_StopPlayback();
// Make sure all callbacks are done. // Make sure all callbacks are done.
DisableInterrupts(); MV_Lock();
for (VoiceNode *voice = VoiceList.next, *next; voice != &VoiceList; voice = next) for (VoiceNode *voice = VoiceList.next, *next; voice != &VoiceList; voice = next)
{ {
@ -774,7 +729,7 @@ static void MV_StopPlayback(void)
MV_StopVoice(voice); MV_StopVoice(voice);
} }
RestoreInterrupts(); MV_Unlock();
} }
static void MV_CalcPanTable(void) static void MV_CalcPanTable(void)
@ -942,3 +897,29 @@ void MV_SetPrintf(void (*function)(const char *, ...)) { MV_Printf = function; }
const char *loopStartTags[loopStartTagCount] = { "LOOP_START", "LOOPSTART", "LOOP" }; const char *loopStartTags[loopStartTagCount] = { "LOOP_START", "LOOPSTART", "LOOP" };
const char *loopEndTags[loopEndTagCount] = { "LOOP_END", "LOOPEND" }; const char *loopEndTags[loopEndTagCount] = { "LOOP_END", "LOOPEND" };
const char *loopLengthTags[loopLengthTagCount] = { "LOOP_LENGTH", "LOOPLENGTH" }; const char *loopLengthTags[loopLengthTagCount] = { "LOOP_LENGTH", "LOOPLENGTH" };
const char *MV_ErrorString(int32_t ErrorNumber)
{
switch (ErrorNumber)
{
case MV_Error:
return MV_ErrorString(MV_ErrorCode);
case MV_Ok:
return "Multivoc ok.";
case MV_NotInstalled:
return "Multivoc not installed.";
case MV_DriverError:
return SoundDriver_ErrorString(SoundDriver_GetError());
case MV_NoVoices:
return "No free voices available to Multivoc.";
case MV_NoMem:
return "Out of memory in Multivoc.";
case MV_VoiceNotFound:
return "No voice with matching handle found.";
case MV_InvalidFile:
return "Invalid file passed in to Multivoc.";
default:
return "Unknown Multivoc error code.";
}
}