Attribute VB_Name = "Sound"
Option Explicit

Public Sound_CountedPhysicsSteps As Long

Public Sound_Wind As Long
Public Sound_Ocean As Long
Public SoundBuffer_Boom As Long
Public SoundBuffer_Foff As Long
Public SoundBuffer_Poff As Long
Public SoundBuffer_Pang As Long
Public SoundBuffer_Pang_Short As Long
Public SoundBuffer_Ch As Long
Public SoundBuffer_Splatt As Long
Public SoundBuffer_Slide As Long
Public SoundBuffer_EngineSpeed As Long
Public SoundBuffer_EngineAccelerate As Long
'Public SoundBuffer_Water As Long
Public SoundBuffer_Gear As Long
Public SoundBuffer_DifferentialLock As Long
'Public SoundBuffer_Waff As Long

'Loads a sound from FileName.
Private Function LoadSound(FileName As String, NumberOfCopies As Long, LoadAs3DSound As Boolean, LoadAsEditable As Boolean) As Long
    InsertStringToEngine "Audio\" & FileName
    LoadSound = frmMain.DGE.Sound_Buffer_LoadFromFile_InSB(NumberOfCopies, LoadAs3DSound, LoadAsEditable): RE
End Function

Private Sub StartAmbientSound(ByRef SoundBuffer As Long, Name As String)
    'The prefix is concatunated to the name before to enforce the naming convention
    SoundBuffer = LoadSound(Name, 1, True, False): RE
    
    'Start playing the sound without any volume
    frmMain.DGE.Sound_Buffer_SetVolume SoundBuffer, 0, 0: RE
    frmMain.DGE.Sound_Buffer_Play SoundBuffer, 0, True, True: RE
End Sub

Private Sub StartSound(SoundBuffer As Long, ByVal Index As Integer)
    frmMain.DGE.Sound_Buffer_Play SoundBuffer, Index, True, True: RE
    frmMain.DGE.Sound_Buffer_SetVolume SoundBuffer, Index, 0: RE
End Sub

Private Sub StopSound(SoundBuffer As Long, ByVal Index As Integer)
    frmMain.DGE.Sound_Buffer_Stop SoundBuffer, Index: RE
End Sub

Public Sub Sound_UseSoundEffect(ByRef VSE As VehicleSoundEffect, Amplitude As Single)
    VSE.EffectSum = VSE.EffectSum + Amplitude
End Sub

Private Sub MoveCloserToGoalAmplitude(Effect As VehicleSoundEffect, ByVal Target As Single, ByVal MaxDiff As Single)
    If Effect.FinalEffect + MaxDiff < Target Then
        Effect.FinalEffect = Effect.FinalEffect + MaxDiff
    ElseIf Effect.FinalEffect - MaxDiff > Target Then
        Effect.FinalEffect = Effect.FinalEffect - MaxDiff
    Else
        Effect.FinalEffect = Target
    End If
End Sub

Private Sub HandleEffect(ByVal SoundBuffer As Long, Effect As VehicleSoundEffect, ByRef TheVehicle As Vehicle, ByVal VehicleIndex As Integer, ByVal MaxDiff As Single, ByVal LowSpeed As Single, ByVal HighSpeed As Single, ByVal LowVolume As Single, ByVal HighVolume As Single)
    'Update amplitude if we had any physical step last render
    Dim VolumeGoal As Single
    If Sound_CountedPhysicsSteps > 0 Then
        'Get the averate amplitude using the sum and number of physics steps
        VolumeGoal = Saturate(Effect.EffectSum / Sound_CountedPhysicsSteps)
        
        'Move closer to the target amplitude
        MoveCloserToGoalAmplitude Effect, VolumeGoal, MaxDiff
        
        'Set the volume and speed
        frmMain.DGE.Sound_Buffer_SetVolume SoundBuffer, VehicleIndex, Lerp(LowVolume, Effect.FinalEffect, HighVolume): RE
        frmMain.DGE.Sound_Buffer_SetSpeed SoundBuffer, VehicleIndex, Lerp(LowSpeed, HighSpeed, Effect.FinalEffect): RE
    End If
    frmMain.DGE.Sound_Buffer_3D_SetPosition SoundBuffer, VehicleIndex, TheVehicle.LastPosition.X, TheVehicle.LastPosition.Y, TheVehicle.LastPosition.Z: RE
    
    'Reset effects
    Effect.EffectSum = 0
End Sub

Public Sub Sound_HandleVehicles()
    'Reset the physics step counter
    Sound_CountedPhysicsSteps = 0
End Sub

Public Sub Sound_Init()
    'Load ambient sounds
    StartAmbientSound Sound_Wind, "Wind"
    StartAmbientSound Sound_Ocean, "Ocean"
    
    'Load vehicle sounds
    SoundBuffer_Slide = LoadSound("Slide", MaxNumberOfVehicles, True, False)
    SoundBuffer_EngineSpeed = LoadSound("EngineSpeed", MaxNumberOfVehicles, True, False)
    SoundBuffer_EngineAccelerate = LoadSound("EngineAccelerate", MaxNumberOfVehicles, True, False)
    'SoundBuffer_Water = LoadSound("Water", MaxNumberOfVehicles, True, False)
    SoundBuffer_Gear = LoadSound("Gear", 4, True, False)
    SoundBuffer_DifferentialLock = LoadSound("DifferentialLock", 2, True, False)
    'SoundBuffer_Waff = LoadSound("Waff", 2, True, False)
    
    'Load other sounds
    'More than 16 copies of the same sound will just waste memory and sound bad
    SoundBuffer_Boom = LoadSound("Boom", 4, True, False)
    SoundBuffer_Foff = LoadSound("Foff", 8, True, False)
    SoundBuffer_Poff = LoadSound("Poff", 4, True, False)
    SoundBuffer_Pang = LoadSound("Pang", 4, True, False)
    SoundBuffer_Pang_Short = LoadSound("Pang_Short", 8, True, False)
    SoundBuffer_Ch = LoadSound("Ch", 4, True, False)
    SoundBuffer_Splatt = LoadSound("Splatt", 16, True, False)
End Sub

Public Sub Sound_Update(EarPos As Vector3, EarDir As Vector3, Volume As Single, OverOcean As Single)
    Dim UnderWater As Single
    UnderWater = Saturate(((Terrain_WaterLevel - EarPos.Y) * 20) + 0.5)
    
    'Listener
    frmMain.DGE.Sound_PlaceGlobalListener EarPos.X, EarPos.Y, EarPos.Z, EarDir.X, EarDir.Y, EarDir.Z, 0, 1, 0: RE
    
    'Wind
    frmMain.DGE.Sound_Buffer_3D_SetPosition Sound_Wind, 0, EarPos.X, Max_Float(EarPos.Y + 0.5, 10), EarPos.Z: RE
    frmMain.DGE.Sound_Buffer_SetVolume Sound_Wind, 0, Volume * (1 - UnderWater): RE
    
    'Ocean
    frmMain.DGE.Sound_Buffer_3D_SetPosition Sound_Ocean, 0, EarPos.X, Min_Float(EarPos.Y, Terrain_WaterLevel), EarPos.Z: RE
    frmMain.DGE.Sound_Buffer_SetVolume Sound_Ocean, 0, Volume * OverOcean * Lerp(0.2, 1, UnderWater): RE
End Sub

Public Sub Sound_StartVehicleLoop(ByVal VehicleIndex As Integer)
    StartSound SoundBuffer_Slide, VehicleIndex
    StartSound SoundBuffer_EngineSpeed, VehicleIndex
    StartSound SoundBuffer_EngineAccelerate, VehicleIndex
End Sub

Public Sub Sound_StopVehicleLoop(ByVal VehicleIndex As Integer)
    StopSound SoundBuffer_Slide, VehicleIndex
    StopSound SoundBuffer_EngineSpeed, VehicleIndex
    StopSound SoundBuffer_EngineAccelerate, VehicleIndex
End Sub

Public Sub Sound_HandleVehicle(ByRef TheVehicle As Vehicle, ByVal VehicleIndex As Integer, ByVal TimePassed As Single)
    HandleEffect SoundBuffer_Slide, TheVehicle.SoundEffects.Slide, TheVehicle, VehicleIndex, TimePassed * 4, 1, 1, 0, 1
    HandleEffect SoundBuffer_EngineAccelerate, TheVehicle.SoundEffects.FuelAcceleration, TheVehicle, VehicleIndex, TimePassed * 30, 1.5, 1.5, 0, 0.2
End Sub



