From 635a92935929cdee46642269517378436da86c2c Mon Sep 17 00:00:00 2001
From: terminx <terminx@1a8010ca-5511-0410-912e-c29ae57300e0>
Date: Wed, 7 Aug 2019 22:44:41 +0000
Subject: [PATCH] Audiolib housekeeping

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

# Conflicts:
#	source/audiolib/src/multivoc.cpp
---
 source/audiolib/src/_multivc.h             |   2 +-
 source/audiolib/src/driver_directsound.cpp |  14 +-
 source/audiolib/src/multivoc.cpp           | 189 +++++++++------------
 3 files changed, 93 insertions(+), 112 deletions(-)

diff --git a/source/audiolib/src/_multivc.h b/source/audiolib/src/_multivc.h
index d094377c0..ba8e2fb98 100644
--- a/source/audiolib/src/_multivc.h
+++ b/source/audiolib/src/_multivc.h
@@ -96,7 +96,7 @@ private:
 };
 
 #define MV_MIXBUFFERSIZE     256
-#define MV_NUMBEROFBUFFERS   16
+#define MV_NUMBEROFBUFFERS   32
 #define MV_TOTALBUFFERSIZE   ( MV_MIXBUFFERSIZE * MV_NUMBEROFBUFFERS )
 
 typedef enum
diff --git a/source/audiolib/src/driver_directsound.cpp b/source/audiolib/src/driver_directsound.cpp
index bf601a52e..b1192485c 100644
--- a/source/audiolib/src/driver_directsound.cpp
+++ b/source/audiolib/src/driver_directsound.cpp
@@ -34,23 +34,23 @@
 
 #define MIXBUFFERPOSITIONS 8
 
-static int32_t ErrorCode = DSErr_Ok;
+static int32_t ErrorCode;
 static int32_t Initialised;
 static int32_t Playing;
 
-static char *  MixBuffer = NULL;
+static char *  MixBuffer;
 static int32_t MixBufferSize;
 static int32_t MixBufferCount;
 static int32_t MixBufferCurrent;
 static int32_t MixBufferUsed;
 
-static void (*MixCallBack)(void) = NULL;
+static void (*MixCallBack)(void);
 
-static LPDIRECTSOUND lpds = NULL;
-static LPDIRECTSOUNDBUFFER lpdsbprimary = NULL, lpdsbsec = NULL;
-static LPDIRECTSOUNDNOTIFY lpdsnotify = NULL;
+static LPDIRECTSOUND lpds;
+static LPDIRECTSOUNDBUFFER lpdsbprimary, lpdsbsec;
+static LPDIRECTSOUNDNOTIFY lpdsnotify;
 
-static HANDLE mixThread = NULL;
+static HANDLE mixThread;
 static mutex_t mutex;
 
 static DSBPOSITIONNOTIFY notifyPositions[MIXBUFFERPOSITIONS + 1] = {};
diff --git a/source/audiolib/src/multivoc.cpp b/source/audiolib/src/multivoc.cpp
index 49ff0a965..9c0dacee0 100644
--- a/source/audiolib/src/multivoc.cpp
+++ b/source/audiolib/src/multivoc.cpp
@@ -88,15 +88,15 @@ int32_t MV_ErrorCode = MV_NotInstalled;
 float MV_GlobalVolume = 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++)
         SoundDriver_Lock();
 }
 
-void RestoreInterrupts(void)
+static inline void MV_Unlock(void)
 {
     if (!--lockdepth)
         SoundDriver_Unlock();
@@ -104,100 +104,73 @@ void RestoreInterrupts(void)
         MV_Printf("RestoreInterrupts(): lockdepth < 0!\n");
 }
 
-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.";
-    }
-}
-
-static bool MV_Mix(VoiceNode *voice, int const buffer)
+static bool MV_Mix(VoiceNode * const voice, int const buffer)
 {
     /* cheap fix for a crash under 64-bit linux */
     /*                            v  v  v  v    */
     if (voice->length == 0 && (voice->GetSound == NULL || voice->GetSound(voice) != KeepPlaying))
         return false;
 
-    int32_t length = MV_MIXBUFFERSIZE;
-    uint32_t FixedPointBufferSize = voice->FixedPointBufferSize;
+    float const gv = MV_GlobalVolume;
+
+    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];
 
     // Add this voice to the mix
     do
     {
-        uint32_t const rate = voice->RateScale;
+        int32_t        mixlen   = length;
         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
         // 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);
-                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)
-            MV_GlobalVolume = 1.f;
-
-        voice->position = voice->mix(voice, voclength);
-
-        MV_GlobalVolume = gv;
-
-        length -= voclength;
-
-        if (voice->position >= voice->length)
+        if (voice->position >= voclen)
         {
             // Get the next block of sound
             if (voice->GetSound(voice) == NoMoreData)
-                return false;
-
-            if (length > (voice->channels - 1))
             {
-                // Get the position of the last sample in the buffer
-                FixedPointBufferSize = voice->RateScale * (length - voice->channels);
+                MV_GlobalVolume = gv;
+                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);
 
+    MV_GlobalVolume = gv;
     return true;
 }
 
 void MV_PlayVoice(VoiceNode *voice)
 {
-    DisableInterrupts();
+    MV_Lock();
     LL::SortedInsert(&VoiceList, voice, &VoiceNode::priority);
     voice->LeftVolume = voice->LeftVolumeDest;
     voice->RightVolume = voice->RightVolumeDest;
-    RestoreInterrupts();
+    MV_Unlock();
 }
 
 static void MV_CleanupVoice(VoiceNode *voice)
@@ -225,12 +198,11 @@ static void MV_CleanupVoice(VoiceNode *voice)
 
 static void MV_StopVoice(VoiceNode *voice)
 {
+    MV_Lock();
     MV_CleanupVoice(voice);
-
-    DisableInterrupts();
     // move the voice from the play list to the free list
     LL::Move(voice, &VoicePool);
-    RestoreInterrupts();
+    MV_Unlock();
 }
 
 /*---------------------------------------------------------------------
@@ -243,15 +215,10 @@ static void MV_StopVoice(VoiceNode *voice)
 static void MV_ServiceVoc(void)
 {
     // Toggle which buffer we'll mix next
-    if (++MV_MixPage >= MV_NumberOfBuffers)
-        MV_MixPage -= MV_NumberOfBuffers;
+    ++MV_MixPage &= MV_NumberOfBuffers-1;
 
     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])
         {
             Bmemset(MV_MixBuffer[MV_MixPage], 0, MV_BufferSize);
@@ -260,48 +227,38 @@ static void MV_ServiceVoc(void)
     }
     else
     {
-        char const *const end = MV_MixBuffer[0] + MV_BufferLength;
-        char *dest = MV_MixBuffer[MV_MixPage];
-        char const *source = MV_MixBuffer[MV_MixPage] - MV_ReverbDelay;
+        char const *const end    = MV_MixBuffer[0] + MV_BufferLength;
+        char *            dest   = MV_MixBuffer[MV_MixPage];
+        char const *      source = MV_MixBuffer[MV_MixPage] - MV_ReverbDelay;
 
         if (source < MV_MixBuffer[ 0 ])
             source += MV_BufferLength;
 
         int32_t length = MV_BufferSize;
 
-        while (length > 0)
+        do
         {
             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
             source  = MV_MixBuffer[ 0 ];
             dest   += count;
             length -= count;
-        }
+        } while (length > 0);
     }
 
-    // Play any waiting voices
-    //DisableInterrupts();
-
-
     if (!VoiceList.next || VoiceList.next == &VoiceList)
         return;
 
     VoiceNode *voice = VoiceList.next;
-
-    int iter = 0;
-
     VoiceNode *next;
 
     do
     {
         next = voice->next;
 
-        if (++iter > MV_MaxVoices && MV_Printf)
-            MV_Printf("more iterations than voices! iter: %d\n",iter);
-
         if (voice->Paused)
             continue;
 
@@ -315,8 +272,6 @@ static void MV_ServiceVoc(void)
         }
     }
     while ((voice = next) != &VoiceList);
-
-    //RestoreInterrupts();
 }
 
 static VoiceNode *MV_GetVoice(int32_t handle)
@@ -328,18 +283,18 @@ static VoiceNode *MV_GetVoice(int32_t handle)
         return NULL;
     }
 
-    DisableInterrupts();
+    MV_Lock();
 
     for (VoiceNode *voice = VoiceList.next; voice != &VoiceList; voice = voice->next)
     {
         if (handle == voice->handle)
         {
-            RestoreInterrupts();
+            MV_Unlock();
             return voice;
         }
     }
 
-    RestoreInterrupts();
+    MV_Unlock();
     MV_SetErrorCode(MV_VoiceNotFound);
     return NULL;
 }
@@ -357,12 +312,12 @@ VoiceNode *MV_BeginService(int32_t handle)
         return NULL;
     }
 
-    DisableInterrupts();
+    MV_Lock();
 
     return voice;
 }
 
-static inline void MV_EndService(void) { RestoreInterrupts(); }
+static inline void MV_EndService(void) { MV_Unlock(); }
 
 int32_t MV_VoicePlaying(int32_t handle)
 {
@@ -374,11 +329,11 @@ int32_t MV_KillAllVoices(void)
     if (!MV_Installed)
         return MV_Error;
 
-    DisableInterrupts();
+    MV_Lock();
 
     if (&VoiceList == VoiceList.next)
     {
-        RestoreInterrupts();
+        MV_Unlock();
         return MV_Ok;
     }
 
@@ -397,7 +352,7 @@ int32_t MV_KillAllVoices(void)
         voice = VoiceList.prev;
     }
 
-    RestoreInterrupts();
+    MV_Unlock();
 
     return MV_Ok;
 }
@@ -420,14 +375,14 @@ int32_t MV_VoicesPlaying(void)
     if (!MV_Installed)
         return 0;
 
-    DisableInterrupts();
+    MV_Lock();
 
     int NumVoices = 0;
 
     for (VoiceNode *voice = VoiceList.next; voice != &VoiceList; voice = voice->next)
         NumVoices++;
 
-    RestoreInterrupts();
+    MV_Unlock();
 
     return NumVoices;
 }
@@ -436,7 +391,7 @@ VoiceNode *MV_AllocVoice(int32_t priority)
 {
     VoiceNode   *voice, *node;
 
-    DisableInterrupts();
+    MV_Lock();
 
     // Check if we have any free voices
     if (LL::Empty(&VoicePool))
@@ -454,14 +409,14 @@ VoiceNode *MV_AllocVoice(int32_t priority)
         if (LL::Empty(&VoicePool))
         {
             // No free voices
-            RestoreInterrupts();
+            MV_Unlock();
             return NULL;
         }
     }
 
     voice = VoicePool.next;
     LL::Remove(voice);
-    RestoreInterrupts();
+    MV_Unlock();
 
     int32_t vhan = MV_MINVOICEHANDLE;
 
@@ -483,7 +438,7 @@ int32_t MV_VoiceAvailable(int32_t priority)
     if (!LL::Empty(&VoicePool))
         return TRUE;
 
-    DisableInterrupts();
+    MV_Lock();
 
     VoiceNode   *voice, *node;
 
@@ -496,11 +451,11 @@ int32_t MV_VoiceAvailable(int32_t priority)
 
     if ((voice == &VoiceList) || (priority < voice->priority))
     {
-        RestoreInterrupts();
+        MV_Unlock();
         return FALSE;
     }
 
-    RestoreInterrupts();
+    MV_Unlock();
     return TRUE;
 }
 
@@ -563,7 +518,7 @@ int32_t MV_SetFrequency(int32_t handle, int32_t frequency)
 
 void MV_SetVoiceMixMode(VoiceNode *voice)
 {
-    int32_t type = T_DEFAULT;
+    int type = T_DEFAULT;
 
     if (MV_Channels == 1)
         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_GetReverbDelay(void) { return MV_ReverbDelay / MV_SampleSize; }
 
 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_NumberOfBuffers = MV_TOTALBUFFERSIZE / MV_BufferSize;
+    Bassert(isPow2(MV_NumberOfBuffers));
     MV_BufferLength = MV_TOTALBUFFERSIZE;
 
     MV_RightChannelOffset = MV_SampleSize >> 1;
@@ -766,7 +721,7 @@ static void MV_StopPlayback(void)
     SoundDriver_StopPlayback();
 
     // Make sure all callbacks are done.
-    DisableInterrupts();
+    MV_Lock();
 
     for (VoiceNode *voice = VoiceList.next, *next; voice != &VoiceList; voice = next)
     {
@@ -774,7 +729,7 @@ static void MV_StopPlayback(void)
         MV_StopVoice(voice);
     }
 
-    RestoreInterrupts();
+    MV_Unlock();
 }
 
 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 *loopEndTags[loopEndTagCount] = { "LOOP_END", "LOOPEND" };
 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.";
+    }
+}
+