#include "sithSoundMixer.h"

#include "AI/sithAIAwareness.h"
#include "Devices/sithControl.h"
#include "Devices/sithSound.h"
#include "Gameplay/sithTime.h"
#include "Engine/sithCamera.h"
#include "Win95/stdSound.h"
#include "Win95/stdMci.h"
#include "Gui/jkGUISound.h"
#include "World/sithWorld.h"
#include "World/sithSector.h"
#include "World/jkPlayer.h"
#include "Dss/sithDSSThing.h"
#include "General/stdMath.h"
#include "jk.h"

int sithSoundMixer_Startup()
{
    if ( !stdMci_Startup() )
        return 1;

    if ( sithSoundMixer_bInitted )
    {
        sithSoundMixer_musicVolume = 1.0;
        stdMci_SetVolume(sithSoundMixer_globalVolume);
    }

    sithSoundMixer_bInitted = 1;
    return 1;
}

void sithSoundMixer_Shutdown()
{
    if ( sithSoundMixer_bInitted )
    {
        stdMci_Shutdown();
        sithSoundMixer_bInitted = 0;
    }
}

int sithSoundMixer_PlaySong(unsigned int trackFrom, unsigned int trackTo, unsigned int trackNum, int a4)
{
    unsigned int trackTo_; // esi
    unsigned int trackFrom_; // edi

    if ( sithSoundMixer_bPlayingMci )
        stdMci_Stop();
    trackTo_ = trackTo;
    if (trackTo <= trackFrom)
        trackTo_ = trackFrom;
    trackFrom_ = trackNum;
    if ( trackNum < trackFrom)
    {
        trackFrom_ = trackFrom;
    }
    else if ( trackNum > trackTo_ )
    {
        trackFrom_ = trackTo_;
    }
    sithSoundMixer_trackFrom = trackFrom;
    sithSoundMixer_bPlayingMci = 1;
    sithSoundMixer_trackTo = trackTo_;
    sithSoundMixer_dword_835FCC = a4;
    if ( !sithSoundMixer_bIsMuted )
    {
        if ( sithSoundMixer_bInitted )
        {
            sithSoundMixer_musicVolume = 1.0;
            stdMci_SetVolume(sithSoundMixer_globalVolume);
        }

        if ( !stdMci_Play(trackFrom_, trackTo_) )
        {
            sithSoundMixer_bPlayingMci = 0;
            return 0;
        }
        if ( a4 )
            sithSoundMixer_flt_835FD8 = sithTime_g_secGameTime - -5.0;
    }
    return 1;
}

void sithSoundMixer_StopSong()
{
    if ( sithSoundMixer_bPlayingMci )
    {
        stdMci_Stop();
        sithSoundMixer_bPlayingMci = 0;
    }
}

void sithSoundMixer_UpdateMusicVolume(flex_t musicVolume)
{
    sithSoundMixer_globalVolume = stdMath_Clamp(musicVolume, 0.0, 1.0);
    if ( sithSoundMixer_globalVolume == 0.0 )
    {
        sithSoundMixer_bIsMuted = 1;
        if ( !sithSoundMixer_bInitted )
            return;
        stdMci_Stop();
    }
    else
    {
        if ( !sithSoundMixer_bInitted )
            return;
        sithSoundMixer_bIsMuted = 0;
        if (sithSoundMixer_bPlayingMci && sithSoundMixer_dword_835FCC)
        {
            sithSoundMixer_flt_835FD8 = sithTime_g_secGameTime - -5.0;
            if ( !stdMci_CheckStatus() && !stdMci_Play(sithSoundMixer_trackFrom, sithSoundMixer_trackTo) )
            {
                sithSoundMixer_bPlayingMci = 0;
                sithSoundMixer_dword_835FCC = 0;
            }
        }
    }
    
    // inlined
    sithSoundMixer_SetMusicVol(sithSoundMixer_musicVolume);
}

void sithSoundMixer_SetMusicVol(flex_t volume)
{
    if ( sithSoundMixer_bInitted )
    {
        sithSoundMixer_musicVolume = stdMath_Clamp(volume, 0.0, 1.0);
        stdMci_SetVolume(sithSoundMixer_globalVolume * sithSoundMixer_musicVolume);
    }
}

void sithSoundMixer_ResumeMusic(int bNotInPauseMenu)
{
    if ( sithSoundMixer_bPlayingMci
      && !sithSoundMixer_bIsMuted
#ifndef QOL_IMPROVEMENTS
      && (bNotInPauseMenu || sithControl_msIdle >= 2000)
#endif
      && sithSoundMixer_dword_835FCC
      && (bNotInPauseMenu || sithSoundMixer_flt_835FD8 <= (flex_d_t)sithTime_g_secGameTime) )
    {
        sithSoundMixer_flt_835FD8 = sithTime_g_secGameTime - -5.0;
        if ( !stdMci_CheckStatus() && !stdMci_Play(sithSoundMixer_trackFrom, sithSoundMixer_trackTo) )
        {
            sithSoundMixer_bPlayingMci = 0;
            sithSoundMixer_dword_835FCC = 0;
        }
    }
}

int sithSoundMixer_Open()
{
    if ( sithSoundMixer_bOpened )
        return 0;

    if ( !sithSound_bInit )
        return 0;
    
    sithSoundMixer_ClearAll();

    sithSoundMixer_bOpened = 1;
    return 1;
}

void sithSoundMixer_Close()
{
    if (!sithSoundMixer_bOpened)
        return;

    for (uint32_t v0 = 0; v0 < sithSoundMixer_numSoundsAvailable; v0++) {
        sithPlayingSound* pPlayingSound = &sithSoundMixer_aPlayingSounds[v0];
        if (pPlayingSound->sound) {
            sithSoundMixer_StopSound(pPlayingSound);    
        }
    }
    sithSoundMixer_hCurAmbientChannel = 0;
    sithSoundMixer_dword_836BFC = 0;
    sithSoundMixer_pCurSector = 0;
    stdSound_IA3D_idk(0.0);
    sithSoundMixer_dword_836C00 = 0;
    sithSoundMixer_pCurSector = 0;
    sithSoundMixer_hCurAmbientChannel = 0;
    sithSoundMixer_dword_836BFC = 0;
    sithSoundMixer_bOpened = 0;
}

void sithSoundMixer_ClearAll()
{
    _memset(sithSoundMixer_aPlayingSounds, 0, sizeof(sithPlayingSound) * SITH_MIXER_NUMPLAYINGSOUNDS);
    for (int i = 0; i < SITH_MIXER_NUMPLAYINGSOUNDS; i++)
    {
        sithSoundMixer_aPlayingSounds[i].idx = i;
    }

    sithSoundMixer_numSoundsAvailable = SITH_MIXER_NUMPLAYINGSOUNDS;
    sithSoundMixer_numSoundsAvailable2 = SITH_MIXER_NUMPLAYINGSOUNDS;

    // Someone please help whoever programmed this    
    for (int i = SITH_MIXER_NUMPLAYINGSOUNDS-1; i >= 0; i--)
    {
        // Setting the index?
        sithSoundMixer_aPlayingSounds[i].idx = i;

        // Ok nvm clearing the struct
        _memset(&sithSoundMixer_aPlayingSounds[i], 0, sizeof(sithPlayingSound));

        // but gotta set that index again
        sithSoundMixer_aPlayingSounds[i].idx = i;
        sithSoundMixer_aIdk[(SITH_MIXER_NUMPLAYINGSOUNDS - 1) - i] = i;
    }

    sithSoundMixer_hCurAmbientChannel = 0;
    sithSoundMixer_dword_836BFC = 0;
    sithSoundMixer_pCurSector = 0;
}

void sithSoundMixer_StopAll()
{
    if (sithNet_isMulti)
        return;
    
    for (uint32_t v0 = 0; v0 < sithSoundMixer_numSoundsAvailable; v0++)
    {
        if ( (sithSoundMixer_aPlayingSounds[v0].flags & SITHSOUNDFLAG_PLAYING) != 0 )
        {
            stdSound_BufferStop(sithSoundMixer_aPlayingSounds[v0].pSoundBuf);
            sithSoundMixer_aPlayingSounds[v0].flags |= SITHSOUNDFLAG_PAUSED;
        }
    }
}

void sithSoundMixer_ResumeAll()
{
    unsigned int v0; // edi

    if (sithNet_isMulti)
        return;

    for (uint32_t v0 = 0; v0 < sithSoundMixer_numSoundsAvailable; v0++)
    {
        if ( (sithSoundMixer_aPlayingSounds[v0].flags & SITHSOUNDFLAG_PAUSED) != 0 )
        {
            if ( sithSoundMixer_aPlayingSounds[v0].pSoundBuf )
                stdSound_BufferPlay(sithSoundMixer_aPlayingSounds[v0].pSoundBuf, sithSoundMixer_aPlayingSounds[v0].flags & SITHSOUNDFLAG_LOOP);
            sithSoundMixer_aPlayingSounds[v0].flags &= ~SITHSOUNDFLAG_PAUSED;
        }
    }
}

sithPlayingSound* sithSoundMixer_PlayingSoundFromSound(sithSound *sound, int flags)
{
    int v3; // eax

    if ( !sithSoundMixer_bOpened )
        return 0;
    if ( sithSoundMixer_numSoundsAvailable2 )
        v3 = sithSoundMixer_aIdk[--sithSoundMixer_numSoundsAvailable2];
    else
        v3 = -1;
    if ( v3 < 0 )
        return 0;

    sithPlayingSound* result = &sithSoundMixer_aPlayingSounds[v3];
    result->sound = sound;
    result->flags = flags;
    result->volumeVelocity = 1.0;
    result->pitch = 1.0;
    if ( sithSoundMixer_channelGUIDSeed == 0 )
        sithSoundMixer_channelGUIDSeed = 1;
    result->refid = sithSoundMixer_channelGUIDSeed++ | ((playerThingIdx + 1) << 16);
    return result;
}

sithPlayingSound* sithSoundMixer_PlaySound(sithSound *hSnd, flex_t volume, flex_t pan, int playflags)
{
    sithPlayingSound *result; // eax
    sithPlayingSound *v6; // ebx
    int v8; // ecx
    int v13; // ecx
    int v15; // esi
    sithPlayingSound* v16;
    sithPlayingSound *v17; // esi
    int v19; // ecx
    sithPlayingSound *v20; // esi
    int v22; // eax
    int v23; // edx
    int v24; // eax
    stdSound_buffer_t *a2b; // [esp+0h] [ebp-10h]
    stdSound_buffer_t *a2d; // [esp+0h] [ebp-10h]

#ifdef STDSOUND_OPENAL
    jkGuiSound_numChannels = SITH_MIXER_NUMPLAYINGSOUNDS;
#endif

    v6 = sithSoundMixer_PlayingSoundFromSound(hSnd, playflags);
    
    if ( !v6 )
        return 0;

    v6->pSoundBuf = sithSound_LoadData(v6->sound);
    if ( !v6->pSoundBuf )
    {
        sithSoundMixer_StopSound(v6);
        return NULL;
    }

    ++v6->sound->field_40;
    stdSound_BufferSetVolume(v6->pSoundBuf, v6->vol_2 * 0.75);
    if ( jkGuiSound_b3DSound )
    {
        v6->p3DSoundObj = stdSound_BufferQueryInterface(v6->pSoundBuf);
        if ( v6->p3DSoundObj )
            stdSound_BufferSetVolume(v6->pSoundBuf, v6->vol_2);
    }
    if ( v6->p3DSoundObj )
        stdSound_3DSetMode(v6->p3DSoundObj, 2);
    v6->vol_2 = stdMath_Clamp(volume, 0.0, 1.5);
    if ( v6->pSoundBuf )
    {
        v13 = v6->flags;
        if ( (v13 & SITHSOUNDFLAG_NO_3D) != 0 || (v13 & (SITHSOUNDFLAG_FOLLOWSTHING|SITHSOUNDFLAG_ABSOLUTE)) == 0 )
        {
            stdSound_BufferSetVolume(v6->pSoundBuf, v6->vol_2 * 0.75);
        }
    }
    stdSound_BufferSetPan(v6->pSoundBuf, pan);
    if ( sithSoundMixer_activeChannels >= jkGuiSound_numChannels )
    {
        v15 = 0;
        while ( sithSoundMixer_dword_836C04 >= SITH_MIXER_NUMPLAYINGSOUNDS )
        {
LABEL_35:
            if ( v15 )
                goto LABEL_46;
            sithSoundMixer_dword_836C04 = 0;
            v15 = 1;
        }

        v16 = &sithSoundMixer_aPlayingSounds[sithSoundMixer_dword_836C04];
        while ( (v16->flags & SITHSOUNDFLAG_PLAYING) == 0 || (v16->flags & (SITHSOUNDFLAG_HIGHEST_PRIO|SITHSOUNDFLAG_HIGHPRIO|SITHSOUNDFLAG_LOOP)) != 0 )
        {
            v16++;
            sithSoundMixer_dword_836C04++;
            if ( v16 >= &sithSoundMixer_aPlayingSounds[SITH_MIXER_NUMPLAYINGSOUNDS] )
                goto LABEL_35;
        }

        v17 = &sithSoundMixer_aPlayingSounds[sithSoundMixer_dword_836C04];
        sithSoundMixer_PlayingSoundReset(v17);

        if ( (sithSoundMixer_aPlayingSounds[sithSoundMixer_dword_836C04].flags & SITHSOUNDFLAG_LOOP) == 0 )
        {
            v20 = &sithSoundMixer_aPlayingSounds[sithSoundMixer_dword_836C04];
            sithSoundMixer_StopSound(v20);
        }
        sithSoundMixer_dword_836C04++;
    }
LABEL_46:
    if ( sithSoundMixer_activeChannels < jkGuiSound_numChannels )
    {
        if ( jkGuiSound_b3DSound )
            stdSound_CommitDeferredSettings();
        stdSound_BufferPlay(v6->pSoundBuf, v6->flags & SITHSOUNDFLAG_LOOP);
        v6->flags |= SITHSOUNDFLAG_PLAYING;
        sithSoundMixer_activeChannels++;
        result = v6;
    }
    else
    {
        sithSoundMixer_StopSound(v6);
        return NULL;
    }
    return result;
}

sithPlayingSound* sithSoundMixer_PlaySoundPos(sithSound *hSnd, rdVector3 *pos, SithSector *pSector, flex_t volume, flex_t minRadius, flex_t maxRadius, int playflags)
{
    int32_t v7; // ebx
    flex_d_t v10; // st7
    sithPlayingSound *v11; // ecx
    int v12; // eax
    sithPlayingSound *v14; // eax
    int v15; // edx
    rdVector3 v16; // [esp+8h] [ebp-Ch] BYREF

    if (!sithSoundMixer_bOpened)
        return NULL;

    volume = stdMath_Clamp(volume, 0.0, 1.5);
    v7 = playflags & ~SITHSOUNDFLAG_PLAYING | SITHSOUNDFLAG_ABSOLUTE;
    if ( pSector && (pSector->flags & SITH_SECTOR_UNDERWATER) != 0 )
        v7 |= SITHSOUNDFLAG_UNDERWATER;

    if (!sithCamera_g_pCurCamera)
        return NULL;
    
    rdVector_Sub3(&v16, pos, &sithCamera_g_pCurCamera->lookPos);
    v10 = rdVector_Normalize3QuickAcc(&v16);
    if ( (v7 & SITHSOUNDFLAG_LOOP) != 0 || v10 <= maxRadius )
    {
        v11 = sithSoundMixer_PlayingSoundFromSound(hSnd, v7);
        if ( v11 )
        {
            v11->pos = *pos;
            v11->vol_2 = volume;
            v11->anonymous_5 = minRadius;
            v11->maxPosition = maxRadius;
            v11->posRelative = v16;
            v11->distance = v10;
            if ( minRadius == maxRadius )
                v11->anonymous_7 = 0.0;
            else
                v11->anonymous_7 = 1.0 / (maxRadius - minRadius);
            return v11;
        }
    }
    return NULL;
}

sithPlayingSound* sithSoundMixer_PlaySoundThing(sithSound *hSnd, SithThing *pThing, flex_t volume, flex_t minRadius, flex_t maxRadius, int playflags)
{
    sithPlayingSound *v11; // esi
    int v12; // eax
    int v14; // eax
    stdSound_buffer_t *v16; // eax
    unsigned int v19; // ecx
    int v20; // edi
    sithPlayingSound* v21; // eax
    sithPlayingSound *v22; // edi
    int v23; // ecx
    int v27; // edx
    int v28; // eax
    stdSound_buffer_t *a2b; // [esp+4h] [ebp-24h]
    stdSound_buffer_t *a2c; // [esp+4h] [ebp-24h]
    flex_t v34; // [esp+18h] [ebp-10h]
    rdVector3 a1; // [esp+1Ch] [ebp-Ch] BYREF

#ifdef STDSOUND_OPENAL
    jkGuiSound_numChannels = SITH_MIXER_NUMPLAYINGSOUNDS;
    //jkGuiSound_b3DSound = 1;
#endif

    // Added: Prevent undef usage
    rdVector_Zero3(&a1);

    v34 = 50.0;
    if (!sithSoundMixer_bOpened)
        return NULL;

    volume = stdMath_Clamp(volume, 0.0, 1.5);
    playflags &= ~SITHSOUNDFLAG_PLAYING;
    playflags |= SITHSOUNDFLAG_FOLLOWSTHING;

    if (sithCamera_g_pCurCamera) {
        rdVector_Sub3(&a1, &pThing->position, &sithCamera_g_pCurCamera->lookPos);
        v34 = rdVector_Normalize3QuickAcc(&a1);
    }
    if ( (playflags & SITHSOUNDFLAG_LOOP) != 0 || (sithCamera_g_pCurCamera && (v34 <= maxRadius)) )
    {
        if ( (pThing->type == SITH_THING_ACTOR || pThing->type == SITH_THING_PLAYER) && (playflags & SITHSOUNDFLAG_VOICE) != 0 && (playflags & SITHSOUNDFLAG_HIGHEST_PRIO|SITHSOUNDFLAG_HIGHPRIO) == 0 )
        {
            if ( pThing->actorParams.field_1BC > sithTime_g_msecGameTime )
                return 0;
            pThing->actorParams.field_1BC = sithTime_g_msecGameTime + hSnd->sound_len;
        }
        if ( pThing == sithPlayer_g_pLocalPlayerThing || pThing->moveType == SITH_MT_PATH || pThing->type == SITH_THING_PLAYER) // Added: third comparison, co-op
        {
            sithAIAwareness_CreateTransmittingEvent(pThing->sector, &pThing->position, 0, maxRadius * 0.6, pThing);
        }

        v11 = sithSoundMixer_PlayingSoundFromSound(hSnd, playflags);

        if ( v11 )
        {
            v11->thing = pThing;
            v11->vol_2 = volume;
            v11->anonymous_5 = minRadius;
            v11->maxPosition = maxRadius;
            rdVector_Copy3(&v11->pos, &pThing->position);
            v11->posRelative = a1;
            v11->distance = v34;
            if ( minRadius == maxRadius )
                v11->anonymous_7 = 0.0;
            else
                v11->anonymous_7 = 1.0 / (maxRadius - minRadius);
            if ( pThing == sithSoundMixer_pFocusedThing )
            {
                v16 = sithSound_LoadData(v11->sound);
                v11->pSoundBuf = v16;
                if ( v16 )
                {
                    ++v11->sound->field_40;
                    stdSound_BufferSetVolume(v11->pSoundBuf, v11->vol_2 * 0.75);
                    if ( jkGuiSound_b3DSound )
                    {
                        v11->p3DSoundObj = stdSound_BufferQueryInterface(v11->pSoundBuf);
                        if ( v11->p3DSoundObj )
                            stdSound_BufferSetVolume(v11->pSoundBuf, v11->vol_2);
                    }
                    v11->flags |= SITHSOUNDFLAG_NO_3D;
                    if ( v11->p3DSoundObj )
                        stdSound_3DSetMode(v11->p3DSoundObj, 2);
                    if ( sithSoundMixer_activeChannels >= jkGuiSound_numChannels )
                    {
                        v19 = sithSoundMixer_dword_836C04;
                        v20 = 0;
                        while ( v19 >= SITH_MIXER_NUMPLAYINGSOUNDS )
                        {
LABEL_46:
                            if ( v20 )
                                goto LABEL_51;
                            v19 = 0;
                            v20 = 1;
                            sithSoundMixer_dword_836C04 = 0;
                        }
                        v21 = &sithSoundMixer_aPlayingSounds[sithSoundMixer_dword_836C04];
                        while ( (v21->flags & SITHSOUNDFLAG_PLAYING) == 0
                             || (v21->flags & (SITHSOUNDFLAG_HIGHEST_PRIO|SITHSOUNDFLAG_HIGHPRIO|SITHSOUNDFLAG_LOOP)) != 0 )
                        {
                            v21++;
                            sithSoundMixer_dword_836C04++;
                            if ( v21 >= &sithSoundMixer_aPlayingSounds[SITH_MIXER_NUMPLAYINGSOUNDS] )
                                goto LABEL_46;
                        }
                        v22 = &sithSoundMixer_aPlayingSounds[sithSoundMixer_dword_836C04];

                        sithSoundMixer_PlayingSoundReset(v22);

                        if ( (sithSoundMixer_aPlayingSounds[sithSoundMixer_dword_836C04].flags & SITHSOUNDFLAG_LOOP) == 0 )
                        {
                            sithSoundMixer_StopSound(&sithSoundMixer_aPlayingSounds[sithSoundMixer_dword_836C04]);
                        }
                        sithSoundMixer_dword_836C04++;
                    }
LABEL_51:
                    if ( sithSoundMixer_activeChannels < jkGuiSound_numChannels )
                    {
                        if ( jkGuiSound_b3DSound )
                            stdSound_CommitDeferredSettings();
                        stdSound_BufferPlay(v11->pSoundBuf, v11->flags & SITHSOUNDFLAG_LOOP);
                        v11->flags |= SITHSOUNDFLAG_PLAYING;
                        sithSoundMixer_activeChannels++;
                        return v11;
                    }
                    if ( (playflags & SITHSOUNDFLAG_LOOP) != 0 )
                        return v11;
                }
                
                sithSoundMixer_StopSound(v11);
                
                return v11;
            }
            if ( v11->p3DSoundObj )
                stdSound_3DSetMode(v11->p3DSoundObj, 0);
            return v11;
            
        }
    }
    return NULL;
}

void sithSoundMixer_PlayingSoundReset(sithPlayingSound *sound)
{
    stdSound_BufferReset(sound->pSoundBuf);
    sound->flags &= ~SITHSOUNDFLAG_PLAYING;
    sithSoundMixer_activeChannels--;
    stdSound_BufferRelease(sound->pSoundBuf);
    sound->pSoundBuf = 0;
    --sound->sound->field_40;
}

void sithSoundMixer_Reset()
{
    for (uint32_t v0 = 0; v0 < sithSoundMixer_numSoundsAvailable; v0++ )
    {
        sithPlayingSound* v1 = &sithSoundMixer_aPlayingSounds[v0];
        if (v1->sound)
        {
            sithSoundMixer_StopSound(v1);
        }
    }
    sithSoundMixer_hCurAmbientChannel = 0;
    sithSoundMixer_pCurSector = 0;
    sithSoundMixer_dword_836BFC = 0;
}

void sithSoundMixer_SetPitch(sithPlayingSound *sound, flex_t pitch, flex_t changetime)
{
    if (changetime > 0.0)
    {
        sound->pitchVel = (pitch - sound->pitch) / changetime;
        if (sound->pitchVel != 0.0)
        {
            sound->nextPitch = pitch;
            sound->flags |= SITHSOUNDFLAG_PER_VEL_PITCH_BEND;
        }
    }
    else if (sithSoundMixer_bOpened)
    {
        sound->pitch = pitch;
        if (sound->sound)
        {
            if (sound->pSoundBuf)
                stdSound_BufferSetFrequency(sound->pSoundBuf, (int)((flex_d_t)sound->sound->sampleRate * pitch));
        }
    }
}

int sithSoundMixer_SetFrequency(sithPlayingSound *sound, flex_t pitch)
{
    if (!sithSoundMixer_bOpened)
        return 0;
    sithSound* pSound = sound->sound;
    sound->pitch = pitch;
    if (!pSound || !sound->pSoundBuf)
        return 0;
    stdSound_BufferSetFrequency(sound->pSoundBuf, (int)((flex_d_t)pSound->sampleRate * pitch));
    return 1;
}

void sithSoundMixer_FadeVolume(sithPlayingSound *hChannel, flex_t volume, flex_t secFadeTime)
{
    flex_d_t v3; // st7
    flex_d_t v7; // st6
    flex_t a2; // [esp+0h] [ebp-4h]

    volume = stdMath_Clamp(volume, 0.0, 1.5);
    v3 = volume - hChannel->vol_2;
    if ( v3 != 0.0 )
    {
        hChannel->flags &= ~(SITHSOUNDFLAG_FADE_OUT|SITHSOUNDFLAG_FADE_IN|SITHSOUNDFLAG_FADING);
        if (secFadeTime == 0.0)
        {
            hChannel->vol_2 = stdMath_Clamp(volume, 0.0, 1.5);
            if ( hChannel->pSoundBuf && ((hChannel->flags & SITHSOUNDFLAG_NO_3D) != 0 || (hChannel->flags & (SITHSOUNDFLAG_FOLLOWSTHING|SITHSOUNDFLAG_ABSOLUTE)) == 0) )
            {
                a2 = hChannel->vol_2 * 0.75;
                stdSound_BufferSetVolume(hChannel->pSoundBuf, a2);
            }
        }
        else
        {
            v7 = v3;
            if (v7 < 0.0) // TODO verify? fadeintime_ < 0.0?
                v7 = -v3;
            hChannel->volumeVelocity = v7 / secFadeTime;
            hChannel->volume = volume;
            if (v3 < 0.0) // TODO verify? sound->volumeVelocity < 0.0? fadeintime_ > 0.0?
                hChannel->flags |= SITHSOUNDFLAG_FADE_OUT;
            else
                hChannel->flags |= SITHSOUNDFLAG_FADE_IN;
        }
    }
}

void sithSoundMixer_SetVolume(sithPlayingSound *hChannel, flex_t volume)
{
    hChannel->vol_2 = stdMath_Clamp(volume, 0.0, 1.5);
    if (!hChannel->pSoundBuf)
        return;

    if ( (hChannel->flags & SITHSOUNDFLAG_NO_3D) != 0 || (hChannel->flags & (SITHSOUNDFLAG_FOLLOWSTHING|SITHSOUNDFLAG_ABSOLUTE)) == 0 )
    {
        stdSound_BufferSetVolume(hChannel->pSoundBuf, hChannel->vol_2 * 0.75);
    }
}

sithPlayingSound* sithSoundMixer_StopSectorSound(sithSound* pSound)
{
    if (!sithSoundMixer_bOpened) {
        return NULL;
    }

    sithPlayingSound* v28 = sithSoundMixer_PlayingSoundFromSound(pSound, 1);
    if ( v28 )
    {
        if (sithSoundMixer_sub_4DD5D0(v28))
        {
            //printf("asdf %s\n", v28->sound->sound_fname);
            if ( v28->p3DSoundObj )
                stdSound_3DSetMode(v28->p3DSoundObj, 2);
            sithSoundMixer_SetVolume(v28, 0.0);
            stdSound_BufferSetPan(v28->pSoundBuf, 0.0);
            if ( sithSoundMixer_sub_4DD3F0(v28) )
            {
                return v28;
            }
        }

        sithSoundMixer_StopSound(v28);
    }

    return NULL;
}

void sithSoundMixer_TickSectorSound()
{
    SithSector *v1; // eax
    sithSound *lastSectorFadingOutSound; // esi
    sithPlayingSound *v3; // ecx
    flex_d_t v4; // st7
    flex_d_t v7; // st6
    flex_d_t v13; // st7
    flex_d_t v14; // st6
    flex_d_t v17; // st6
    flex_d_t v20; // st7
    flex_d_t v23; // st6
    flex_d_t v31; // st6
    flex_t v43; // [esp+4h] [ebp-10h]

    v1 = sithCamera_g_pCurCamera->sector;
    if ( v1 == sithSoundMixer_pCurSector )
        return;

    // Added: nullptr deref crash fix
    if (!v1)
        return;

    sithSoundMixer_pCurSector = sithCamera_g_pCurCamera->sector;
    if ( sithSoundMixer_dword_836C00 && (v1->flags & 2) == 0)
    {
        stdSound_IA3D_idk(1.0);
        sithSoundMixer_dword_836C00 = 0;
    }
    else if ( (v1->flags & 2) != 0 )
    {
        stdSound_IA3D_idk(2.0);
        sithSoundMixer_dword_836C00 = 1;
    }

    // why was it like this before?
    /*else if ( sithSoundMixer_dword_836C00 )
    {
        if ( (v1->flags & 2) == 0 )
        {
            stdSound_IA3D_idk(1.0);
            sithSoundMixer_dword_836C00 = 0;
        }
    }*/

    lastSectorFadingOutSound = sithSoundMixer_pCurSector->hAmbientSound;
    if ( sithSoundMixer_pCurSector->ambientSoundVolume == 0.0 )
        lastSectorFadingOutSound = NULL;
    v3 = sithSoundMixer_hCurAmbientChannel;
    if (!lastSectorFadingOutSound && sithSoundMixer_hCurAmbientChannel)
    {
        v4 = -sithSoundMixer_hCurAmbientChannel->vol_2;
        if (v4 == 0.0)
        {
            sithSoundMixer_hCurAmbientChannel->flags |= SITHSOUNDFLAG_FADING;
            sithSoundMixer_hCurAmbientChannel = NULL;
            
        }
        else
        {
            v3->flags &= ~(SITHSOUNDFLAG_FADE_OUT|SITHSOUNDFLAG_FADE_IN|SITHSOUNDFLAG_FADING);
            v7 = stdMath_Fabs(v4);
            v3->volume = 0.0;
            v3->volumeVelocity = v7 + v7;
            if (v4 < 0.0) // TODO verify? v4
                v3->flags |= SITHSOUNDFLAG_FADE_OUT;
            else
                v3->flags |= SITHSOUNDFLAG_FADE_IN;
            sithSoundMixer_hCurAmbientChannel = NULL;
            v3->flags |= SITHSOUNDFLAG_FADING;
        }
        return;
    }

    if (!lastSectorFadingOutSound)
        return;

    if (!sithSoundMixer_hCurAmbientChannel)
    {
        sithSoundMixer_hCurAmbientChannel = sithSoundMixer_StopSectorSound(lastSectorFadingOutSound);

        if (sithSoundMixer_hCurAmbientChannel)
            sithSoundMixer_FadeVolume(sithSoundMixer_hCurAmbientChannel, sithSoundMixer_pCurSector->ambientSoundVolume, 0.5);
        return;
    }

    if (sithSoundMixer_hCurAmbientChannel->sound == lastSectorFadingOutSound)
    {
        v13 = stdMath_Clamp(sithSoundMixer_pCurSector->ambientSoundVolume, 0.0, 1.5);
        v14 = v13 - sithSoundMixer_hCurAmbientChannel->vol_2;
        if ( v14 == 0.0 )
            return;
        v17 = stdMath_Fabs(v14);

        // added copy for later
        v43 = v14;

        sithSoundMixer_hCurAmbientChannel->flags &= ~(SITHSOUNDFLAG_FADE_OUT|SITHSOUNDFLAG_FADE_IN|SITHSOUNDFLAG_FADING);
    }
    else
    {
        v20 = -sithSoundMixer_hCurAmbientChannel->vol_2;
        if (v20 != 0.0)
        {
            sithSoundMixer_hCurAmbientChannel->flags &= ~(SITHSOUNDFLAG_FADE_OUT|SITHSOUNDFLAG_FADE_IN|SITHSOUNDFLAG_FADING);
            v23 = stdMath_Fabs(v20);
            v3->volume = 0.0;
            v3->volumeVelocity = v23 + v23;
            if (v20 < 0.0) // TODO verify? v20 <
                v3->flags |= SITHSOUNDFLAG_FADE_OUT;
            else
                v3->flags |= SITHSOUNDFLAG_FADE_IN;
        }
        //printf("%s fade\n", v3->sound->sound_fname);
        v3->flags |= SITHSOUNDFLAG_FADING;
        v3 = sithSoundMixer_StopSectorSound(lastSectorFadingOutSound);
        sithSoundMixer_hCurAmbientChannel = v3;
        if (!v3)
            return;
        v13 = stdMath_Clamp(sithSoundMixer_pCurSector->ambientSoundVolume, 0.0, 1.5);
        v31 = v13 - v3->vol_2;
        if (v31 == 0.0)
            return;
        v43 = v31;
        v17 = stdMath_Fabs(v43);
        v3->flags &= ~(SITHSOUNDFLAG_FADE_OUT|SITHSOUNDFLAG_FADE_IN|SITHSOUNDFLAG_FADING);
    }
    v3->volumeVelocity = v17 + v17;
    v3->volume = v13;
    if (v43 < 0.0) // TODO verify? v43 > 0.0
        v3->flags |= SITHSOUNDFLAG_FADE_OUT;
    else
        v3->flags |= SITHSOUNDFLAG_FADE_IN;
    
    return;
}

void sithSoundMixer_Update(flex_t deltaSecs)
{
    rdVector3 tmp;

#ifdef STDSOUND_OPENAL
    jkGuiSound_numChannels = SITH_MIXER_NUMPLAYINGSOUNDS;
#endif

    if ( !sithCamera_g_pCurCamera )
        return;
    if ( (sithCamera_g_pCurCamera->type & 0xFC) != 0 )
        sithSoundMixer_pFocusedThing = 0;
    else
        sithSoundMixer_pFocusedThing = sithWorld_g_pCurrentWorld->pCameraFocusThing;

    // This was inlined, TODO check Jones3D and see if it had a name
    sithSoundMixer_TickSectorSound();

    for (uint32_t i = 0; i < sithSoundMixer_numSoundsAvailable; i++)
    {
        sithPlayingSound* soundIter = &sithSoundMixer_aPlayingSounds[i];
        if ( soundIter->sound )
        {
            //jk_printf("tick %u: %s %x, %f %f vol %f\n", i, soundIter->sound->sound_fname, soundIter->flags, soundIter->distance, soundIter->maxPosition, soundIter->vol_2);
            sithSoundMixer_TickPlayingSound(soundIter, deltaSecs);
        }
    }
    //printf("--- %u\n", sithSoundMixer_activeChannels);
    rdVector_Scale3(&tmp, &sithCamera_g_pCurCamera->lookPos, 10.0);
    stdSound_SetPositionOrientation(&tmp, &sithCamera_g_pCurCamera->orient.lvec, &sithCamera_g_pCurCamera->orient.uvec);
}

void sithSoundMixer_TickPlayingSound(sithPlayingSound *sound, flex_t deltaSecs)
{
    flex_d_t v4; // st7
    int v8; // eax
    sithSound *v9; // eax
    stdSound_buffer_t *v10; // eax
    sithSound *v18; // eax
    int v20; // eax
    sithSound *v21; // eax
    int v23; // ecx
    sithSound *v24; // eax
    int v26; // edx
    int v27; // eax
    stdSound_buffer_t *a2a; // [esp+0h] [ebp-18h]
    stdSound_buffer_t *a2c; // [esp+0h] [ebp-18h]
    flex_t a1a; // [esp+1Ch] [ebp+4h]
    flex_t deltaSecsa; // [esp+20h] [ebp+8h]

    if (!sound->sound)
        return;

    if (sound->flags & SITHSOUNDFLAG_FADE_OUT)
    {
        v4 = sound->vol_2 - sound->volumeVelocity * deltaSecs;
        a1a = v4;
        if (v4 <= sound->volume)
        {
            a1a = sound->volume;
            sound->flags &= ~SITHSOUNDFLAG_FADE_OUT;
        }
        
        sound->vol_2 = stdMath_Clamp(a1a, 0.0, 1.5);
        if (sound->pSoundBuf)
        {
            if ((sound->flags & SITHSOUNDFLAG_NO_3D) != 0
              || !(sound->flags & (SITHSOUNDFLAG_FOLLOWSTHING|SITHSOUNDFLAG_ABSOLUTE)))
            {
                stdSound_BufferSetVolume(sound->pSoundBuf, sound->vol_2 * 0.75);
            }
        }

        if ((sound->flags & SITHSOUNDFLAG_FADING) && a1a <= 0.0 )
        {
            sithSoundMixer_StopSound(sound);
        }
    }

    if (sound->flags & SITHSOUNDFLAG_FADE_IN)
    {
        flex_d_t v11 = sound->volumeVelocity * deltaSecs + sound->vol_2;
        if ( v11 >= sound->volume )
        {
            v11 = sound->volume;
            sound->flags &= ~SITHSOUNDFLAG_FADE_IN;
        }

        sound->vol_2 = stdMath_Clamp(v11, 0.0, 1.5);
        if (sound->pSoundBuf)
        {
            if ((sound->flags & SITHSOUNDFLAG_NO_3D) != 0
              || !(sound->flags & (SITHSOUNDFLAG_FOLLOWSTHING|SITHSOUNDFLAG_ABSOLUTE)))
            {
                stdSound_BufferSetVolume(sound->pSoundBuf, sound->vol_2 * 0.75);
            }
        }
    }

    if (sound->flags & SITHSOUNDFLAG_PER_VEL_PITCH_BEND)
    {
        deltaSecsa = sound->pitchVel * deltaSecs + sound->pitch;
        if (sound->pitchVel > 0.0 && deltaSecsa > (flex_d_t)sound->nextPitch || sound->pitchVel < 0.0 && deltaSecsa < (flex_d_t)sound->nextPitch) // TODO verify sound->pitchVel > 0
        {
            sound->flags &= ~SITHSOUNDFLAG_PER_VEL_PITCH_BEND;
            deltaSecsa = sound->nextPitch;
        }
        sithSoundMixer_SetFrequency(sound, deltaSecsa);
    }

    if ((sound->flags & SITHSOUNDFLAG_PLAYING) && !(sound->flags & SITHSOUNDFLAG_LOOP) && !stdSound_IsPlaying(sound->pSoundBuf, 0))
    {
        sithSoundMixer_StopSound(sound);
    }

    if (!(sound->flags & SITHSOUNDFLAG_NO_3D)
      && (sound->flags & (SITHSOUNDFLAG_FOLLOWSTHING|SITHSOUNDFLAG_ABSOLUTE)))
    {
        sithSoundMixer_UpdatePlayingSoundPosition(sound);
        if (sound->distance <= (flex_d_t)sound->maxPosition)
        {
            if (!sound->pSoundBuf)
            {
                sound->pSoundBuf = sithSound_LoadData(sound->sound);
                if ( !sound->pSoundBuf )
                {
                    sithSoundMixer_StopSound(sound);
                    return;
                }
                ++sound->sound->field_40;
                stdSound_BufferSetVolume(sound->pSoundBuf, sound->vol_2 * 0.75);
                if (jkGuiSound_b3DSound)
                {
                    sound->p3DSoundObj = stdSound_BufferQueryInterface(sound->pSoundBuf);
                    if (sound->p3DSoundObj)
                        stdSound_BufferSetVolume(sound->pSoundBuf, sound->vol_2);
                }
                if ( sound->p3DSoundObj && (sound->flags & SITHSOUNDFLAG_NO_3D) == 0 )
                    stdSound_3DSetMode(sound->p3DSoundObj, 0);
            }
            sithSoundMixer_UpdateSoundPos(sound);
            if (sound->flags & SITHSOUNDFLAG_DOPPLER)
                sithSoundMixer_SetVelocity(sound);
            if (!(sound->flags & SITHSOUNDFLAG_PLAYING))
                sithSoundMixer_sub_4DD3F0(sound);
        }
        else
        {
            if (sound->flags & SITHSOUNDFLAG_PLAYING)
            {
                sithSoundMixer_PlayingSoundReset(sound);
            }
            
            // Added: adjusted this so that sounds actually free?
            // TODO figure out why this needed to be changed
            if (!(sound->flags & SITHSOUNDFLAG_LOOP)) 
            {
                sithSoundMixer_StopSound(sound);
            }
        }
    }
}

void sithSoundMixer_UpdateSoundPos(sithPlayingSound *sound)
{
    flex_d_t v2; // st7
    stdSound_buffer_t *v5; // eax
    flex_d_t v6; // st6
    flex_d_t v8; // st6
    flex_d_t v9; // st6
    flex_t a2; // [esp+0h] [ebp-18h]
    flex_t v16; // [esp+8h] [ebp-10h]
    rdVector3 v17; // [esp+Ch] [ebp-Ch] BYREF
    flex_t a1a; // [esp+1Ch] [ebp+4h]

    v2 = sound->vol_2;
    v16 = sound->vol_2;
    if (sound->p3DSoundObj)
    {
        v8 = sound->distance - sound->anonymous_5;
        if (v8 > 0.0)
        {
            v9 = stdMath_Clamp(v8 * sound->anonymous_7, 0.0, 1.0);
            v2 = v2 * (1.0 - v9);
        }

        stdSound_BufferSetVolume(sound->pSoundBuf, stdMath_Clamp(v2, 0.0, 1.5) * 0.75);
        rdVector_Scale3(&v17, &sound->pos, 10.0);
        stdSound_SetPosition(sound->p3DSoundObj, &v17);
    }
    else
    {
        if (!(sound->flags & SITHSOUNDFLAG_AMBIENT_NOPAN))
        {
            v5 = sound->pSoundBuf;
            a1a = rdVector_Dot3(&sithCamera_g_pCurCamera->orient.lvec, &sound->posRelative);
            a2 = rdVector_Dot3(&sithCamera_g_pCurCamera->orient.rvec, &sound->posRelative);

            stdSound_BufferSetPan(v5, a2);
            if (a1a >= 0.0)
                v2 = v16;
            else
                v2 = (1.0 - -a1a * 0.3) * v16;
        }
        v6 = sound->distance - sound->anonymous_5;
        if ( v6 > 0.0 )
        {
            v2 *= (1.0 - stdMath_Clamp(v6 * sound->anonymous_7, 0.0, 1.0));
        }
        stdSound_BufferSetVolume(sound->pSoundBuf, stdMath_Clamp(v2, 0.0, 1.0) * 0.75);
    }
}

void sithSoundMixer_SetVelocity(sithPlayingSound *sound)
{
    rdVector3 tmp;

    if (!sound->thing)
    {
        sound->flags &= ~SITHSOUNDFLAG_DOPPLER;
        return;
    }

    if (sound->p3DSoundObj && sound->thing->moveType == SITH_MT_PHYSICS)
    {
        rdVector_Scale3(&tmp, &sound->thing->physicsParams.vel, 10.0);
        stdSound_SetVelocity(sound->p3DSoundObj, &tmp);
    }
}

void sithSoundMixer_SyncSounds()
{
    for (int i = 0; i < SITH_MIXER_NUMPLAYINGSOUNDS; i++)
    {
        sithPlayingSound* iter = &sithSoundMixer_aPlayingSounds[i];
        if (iter != sithSoundMixer_hCurAmbientChannel)
        {
            sithSound* pSound = iter->sound;
            if (pSound)
            {
                if (iter->flags & SITHSOUNDFLAG_LOOP)
                    sithDSSThing_PlaySound(
                        iter->thing,
                        &iter->pos,
                        pSound,
                        iter->anonymous_5,
                        iter->maxPosition,
                        iter->flags,
                        iter->refid,
                        -1,
                        255);
            }
        }
        ++iter;
    }
}

void sithSoundMixer_FreePlayingSound(sithPlayingSound *sound)
{
    // Save the index before clearing
    int saveIdx = sound->idx;
    _memset(sound, 0, sizeof(sithPlayingSound));

    sound->idx = saveIdx;
    sithSoundMixer_aIdk[sithSoundMixer_numSoundsAvailable2++] = sound->idx;
}

void sithSoundMixer_FreeThing(SithThing *thing)
{
    if (!sithSoundMixer_bOpened)
        return;

    for (uint32_t i = 0; i < sithSoundMixer_numSoundsAvailable; i++)
    {
        sithPlayingSound* playingSound = &sithSoundMixer_aPlayingSounds[i];
        
        if ((playingSound->flags & SITHSOUNDFLAG_FOLLOWSTHING) && thing == playingSound->thing)
        {
            if (playingSound->flags & SITHSOUNDFLAG_LOOP)
            {
                sithSoundMixer_StopSound(playingSound);
            }
            else
            {
                playingSound->flags &= ~SITHSOUNDFLAG_FOLLOWSTHING;
                playingSound->flags |= SITHSOUNDFLAG_ABSOLUTE;
                rdVector_Copy3(&playingSound->pos, &thing->position);
            }
        }
    }
}

sithPlayingSound* sithSoundMixer_GetChannelHandle(int guid)
{
    unsigned int playingsound_idx; // ecx

    if ( !guid )
        return NULL;

    playingsound_idx = 0;
    for (int i = 0; i < SITH_MIXER_NUMPLAYINGSOUNDS; i++)
    {
        if (sithSoundMixer_aPlayingSounds[i].sound && sithSoundMixer_aPlayingSounds[i].refid == guid)
            break;
        ++playingsound_idx;
    }

    if (playingsound_idx < SITH_MIXER_NUMPLAYINGSOUNDS)
        return &sithSoundMixer_aPlayingSounds[playingsound_idx];
    else
        return NULL;
}

void sithSoundMixer_UpdatePlayingSoundPosition(sithPlayingSound *sound)
{
    if ( (sound->flags & SITHSOUNDFLAG_ABSOLUTE) != 0 )
    {
        rdVector_Sub3(&sound->posRelative, &sound->pos, &sithCamera_g_pCurCamera->lookPos);
    }
    else
    {
        SithThing* pThing = sound->thing;
        rdVector_Copy3(&sound->pos, &pThing->position);
        rdVector_Sub3(&sound->posRelative, &sound->pos, &sithCamera_g_pCurCamera->lookPos);
        
        if ( pThing->sector && !(pThing->sector->flags & SITH_SECTOR_UNDERWATER)) // Added: nullptr check, pThing->sector
            sound->flags &= ~SITHSOUNDFLAG_UNDERWATER;
        else
            sound->flags |= SITHSOUNDFLAG_UNDERWATER;
    }

    if ( stdMath_Fabs(sound->posRelative.x) > sound->maxPosition
         || stdMath_Fabs(sound->posRelative.y) > sound->maxPosition
         || stdMath_Fabs(sound->posRelative.z) > sound->maxPosition)
    {
        sound->distance = sound->maxPosition - -1.0;
    }
    else
    {
        flex_t dist = rdVector_Normalize3QuickAcc(&sound->posRelative);
        sound->distance = dist;
        if ( dist > sound->maxPosition ) // TODO verify
        {
            if ( (sound->flags & SITHSOUNDFLAG_UNDERWATER) == 0 || (sithCamera_g_pCurCamera->sector->flags & SITH_SECTOR_UNDERWATER) != 0 )
            {
                if ( (sound->flags & SITHSOUNDFLAG_UNDERWATER) == 0 && (sithCamera_g_pCurCamera->sector->flags & SITH_SECTOR_UNDERWATER) != 0 )
                    sound->distance = dist * 1.5;
            }
            else
            {
                sound->distance = dist * 1.5;
            }
        }
    }
}

void sithSoundMixer_SetSectorAmbientSound(SithSector *pSector, sithSound *hSnd, flex_t volume)
{
    pSector->hAmbientSound = hSnd;
    pSector->ambientSoundVolume = volume;
    if ( sithSoundMixer_pCurSector == pSector )
        sithSoundMixer_pCurSector = 0;
}

int sithSoundMixer_sub_4DD3F0(sithPlayingSound *sound)
{
    unsigned int v1; // ecx
    int v2; // esi
    sithPlayingSound* v3; // eax
    sithPlayingSound *v4; // esi
    int v5; // ecx
    int v8; // eax
    int v9; // edx
    stdSound_buffer_t *v13; // [esp-4h] [ebp-Ch]
    stdSound_buffer_t *v14; // [esp-4h] [ebp-Ch]

#ifdef STDSOUND_OPENAL
    jkGuiSound_numChannels = SITH_MIXER_NUMPLAYINGSOUNDS;
    //jkGuiSound_b3DSound = 1;
#endif

    if ( sithSoundMixer_activeChannels >= jkGuiSound_numChannels )
    {
        v2 = 0;
        while ( sithSoundMixer_dword_836C04 >= SITH_MIXER_NUMPLAYINGSOUNDS )
        {
LABEL_8:
            if ( v2 )
                goto LABEL_19;
            sithSoundMixer_dword_836C04 = 0;
            v2 = 1;
        }
        v3 = &sithSoundMixer_aPlayingSounds[sithSoundMixer_dword_836C04];
        while ( (v3->flags & SITHSOUNDFLAG_PLAYING) == 0 || (v3->flags & (SITHSOUNDFLAG_HIGHEST_PRIO|SITHSOUNDFLAG_HIGHPRIO|SITHSOUNDFLAG_LOOP)) != 0 )
        {
            v3++;
            sithSoundMixer_dword_836C04++;
            if ( v3 >= &sithSoundMixer_aPlayingSounds[SITH_MIXER_NUMPLAYINGSOUNDS] )
                goto LABEL_8;
        }

        v4 = &sithSoundMixer_aPlayingSounds[sithSoundMixer_dword_836C04];
        sithSoundMixer_PlayingSoundReset(v4);

        if ( (sithSoundMixer_aPlayingSounds[sithSoundMixer_dword_836C04].flags & SITHSOUNDFLAG_LOOP) == 0 )
        {
            sithSoundMixer_StopSound(&sithSoundMixer_aPlayingSounds[sithSoundMixer_dword_836C04]);
        }
        sithSoundMixer_dword_836C04++;
    }
LABEL_19:

    //printf("%u\n", sithSoundMixer_activeChannels);

    if ( sithSoundMixer_activeChannels >= jkGuiSound_numChannels )
        return 0;
    if ( jkGuiSound_b3DSound )
        stdSound_CommitDeferredSettings();
    stdSound_BufferPlay(sound->pSoundBuf, sound->flags & SITHSOUNDFLAG_LOOP);
    sound->flags |= SITHSOUNDFLAG_PLAYING;
    sithSoundMixer_activeChannels++;
    return 1;
}

int sithSoundMixer_sub_4DD5D0(sithPlayingSound *sound)
{
    sound->pSoundBuf = sithSound_LoadData(sound->sound);
    if ( sound->pSoundBuf )
    {
        flex_t a2 = sound->vol_2 * 0.75;
        ++sound->sound->field_40;
        stdSound_BufferSetVolume(sound->pSoundBuf, a2);
        if ( jkGuiSound_b3DSound )
        {
            sound->p3DSoundObj = stdSound_BufferQueryInterface(sound->pSoundBuf);
            if ( sound->p3DSoundObj )
                stdSound_BufferSetVolume(sound->pSoundBuf, sound->vol_2);
        }
        return 1;
    }
    return 0;
}

int32_t sithSoundMixer_GetThingSoundIdx(SithThing *thing, sithSound *sound)
{
    if ( !sithSoundMixer_numSoundsAvailable ) {
        //printf("no sounds available\n");
        return -1;
    }

    for (int i = 0; i < sithSoundMixer_numSoundsAvailable; i++) {
        if (sithSoundMixer_aPlayingSounds[i].sound == sound) {
            if (!thing)
                return i;
            if (thing && sithSoundMixer_aPlayingSounds[i].thing == thing) {
                return i;
            }
        }
    }


    return -1;
}

void sithSoundMixer_StopSound(sithPlayingSound *hChannel)
{
    if (!hChannel) return; // Added

    if ( (hChannel->flags & SITHSOUNDFLAG_PLAYING) != 0 )
    {
        sithSoundMixer_PlayingSoundReset(hChannel);
    }
    if ( hChannel->pSoundBuf )
    {
        stdSound_BufferRelease(hChannel->pSoundBuf);
        hChannel->pSoundBuf = 0;
    }
    if ( hChannel->p3DSoundObj )
    {
        stdSound_3DBufferRelease(hChannel->p3DSoundObj);
        hChannel->p3DSoundObj = 0;
    }

    sithSoundMixer_FreePlayingSound(hChannel);
}

sithPlayingSound* sithSoundMixer_GetSoundFromIdx(int idx)
{
    if (idx >= 0 && idx < SITH_MIXER_NUMPLAYINGSOUNDS)
        return &sithSoundMixer_aPlayingSounds[idx];

    return NULL;
}
