first commit
This commit is contained in:
119
Code/Utils/EngineStream/EngineStreamPlayer.cs
Normal file
119
Code/Utils/EngineStream/EngineStreamPlayer.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
using Sandbox;
|
||||
using Sandbox.Audio;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using VeloX.Audio;
|
||||
using static VeloX.EngineStream;
|
||||
|
||||
namespace VeloX;
|
||||
|
||||
public class EngineStreamPlayer( EngineStream stream ) : IDisposable
|
||||
{
|
||||
|
||||
private static readonly Mixer EngineMixer = Mixer.FindMixerByName( "Car Engine" );
|
||||
public EngineStream Stream { get; set; } = stream;
|
||||
|
||||
public EngineState EngineState { get; set; }
|
||||
public bool EngineSoundPaused => EngineState != EngineState.Running;
|
||||
|
||||
public float Throttle { get; set; }
|
||||
public bool IsRedlining { get; set; }
|
||||
public float RPMPercent { get; set; }
|
||||
|
||||
private float _wobbleTime;
|
||||
|
||||
public readonly Dictionary<Layer, SoundHandle> EngineSounds = [];
|
||||
|
||||
public void Update( float deltaTime, Vector3 position, bool isLocal = false )
|
||||
{
|
||||
var globalPitch = 1.0f;
|
||||
|
||||
// Gear wobble effect
|
||||
if ( _wobbleTime > 0 )
|
||||
{
|
||||
_wobbleTime -= deltaTime * (0.1f + Throttle);
|
||||
globalPitch += MathF.Cos( _wobbleTime * Stream.Parameters.WobbleFrequency ) * _wobbleTime * (1 - _wobbleTime) * Stream.Parameters.WobbleStrength;
|
||||
}
|
||||
|
||||
globalPitch *= Stream.Parameters.Pitch;
|
||||
|
||||
// Redline effect
|
||||
var redlineVolume = 1.0f;
|
||||
if ( IsRedlining )
|
||||
{
|
||||
redlineVolume = 1 - Stream.Parameters.RedlineStrength +
|
||||
MathF.Cos( RealTime.Now * Stream.Parameters.RedlineFrequency ) *
|
||||
Stream.Parameters.RedlineStrength;
|
||||
|
||||
}
|
||||
// Process layers
|
||||
foreach ( var (id, layer) in Stream.Layers )
|
||||
{
|
||||
EngineSounds.TryGetValue( layer, out var channel );
|
||||
|
||||
if ( !channel.IsValid() )
|
||||
{
|
||||
channel = Sound.PlayFile( layer.AudioPath );
|
||||
EngineSounds[layer] = channel;
|
||||
}
|
||||
|
||||
if ( channel.Paused && (EngineSoundPaused || layer.IsMuted) )
|
||||
continue;
|
||||
|
||||
// Reset controller outputs
|
||||
float layerVolume = 1.0f;
|
||||
float layerPitch = 1.0f;
|
||||
|
||||
// Apply all controllers
|
||||
foreach ( var controller in layer.Controllers )
|
||||
{
|
||||
var inputValue = controller.InputParameter switch
|
||||
{
|
||||
Controller.InputTypes.Throttle => Throttle,
|
||||
Controller.InputTypes.RpmFraction => RPMPercent,
|
||||
_ => 0.0f
|
||||
};
|
||||
|
||||
var normalized = Math.Clamp( inputValue, controller.InputRange.Min, controller.InputRange.Max );
|
||||
var outputValue = controller.InputRange.Remap(
|
||||
normalized,
|
||||
controller.OutputRange.Min,
|
||||
controller.OutputRange.Max
|
||||
);
|
||||
|
||||
// Apply to correct parameter
|
||||
switch ( controller.OutputParameter )
|
||||
{
|
||||
case Controller.OutputTypes.Volume:
|
||||
layerVolume *= outputValue;
|
||||
break;
|
||||
case Controller.OutputTypes.Pitch:
|
||||
layerPitch *= outputValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply redline effect if needed
|
||||
layerVolume *= layer.UseRedline ? redlineVolume : 1.0f;
|
||||
layerPitch *= globalPitch;
|
||||
// Update audio channel
|
||||
channel.Pitch = layerPitch;
|
||||
channel.Volume = layerVolume * Stream.Parameters.Volume;
|
||||
channel.Position = position;
|
||||
channel.ListenLocal = isLocal;
|
||||
channel.Paused = EngineSoundPaused || layer.IsMuted;
|
||||
channel.TargetMixer = EngineMixer;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach ( var item in EngineSounds )
|
||||
{
|
||||
item.Value?.Stop();
|
||||
item.Value?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user