sasalka/Code/Sounds/DspReverb.cs
2025-06-08 23:43:22 +03:00

107 lines
2.6 KiB
C#

using Sandbox;
using Sandbox.Audio;
using System.Threading;
using System.Threading.Tasks;
namespace Sandbox;
public sealed class DSPReverb : Component, Component.ITriggerListener
{
[Property] public MixerHandle TargetMixer { get; set; }
[Property] public DspPresetHandle Preset { get; set; }
[Property] [Range( 0f, 10f, 0.1f )] public float FadeDuration { get; set; } = 1f;
[Property] public BBox Bounds { get; set; } = new BBox( Vector3.One * -100f, Vector3.One * 100f );
private DspProcessor _processor;
private BoxCollider _triggerCollider;
private CancellationTokenSource _cts;
protected override void OnAwake()
{
base.OnAwake();
_triggerCollider = Components.Create<BoxCollider>();
_triggerCollider.IsTrigger = true;
_triggerCollider.Static = true;
_triggerCollider.Scale = Bounds.Size;
_triggerCollider.Center = Bounds.Center;
}
public void OnTriggerEnter( Collider other )
{
if ( other.Components.TryGet<Dedugan>( out Dedugan dedugan ) )
{
if ( dedugan.Connection == Dedugan.Local.Connection )
{
_cts?.Cancel();
_cts = new CancellationTokenSource();
if ( _processor != null ) { TargetMixer.Get().RemoveProcessor( _processor ); }
_processor = new DspProcessor( Preset.Name );
_processor.Mix = 0f;
TargetMixer.Get().AddProcessor( _processor );
_processor.Mix = 1f;
// _ = UpdateMixAsync(1f);
}
}
}
private async Task UpdateMixAsync( float targetMix )
{
float startMix = _processor.Mix;
float elapsed = FadeDuration *
((targetMix == 0f || startMix == 0f) ? 0f : Math.Min( startMix / targetMix, 1f ));
float lastTime = Time.Now;
while ( elapsed < FadeDuration && !_cts.IsCancellationRequested )
{
await Task.FixedUpdate();
float delta = Time.Now - lastTime;
elapsed += delta;
float t = Math.Clamp( elapsed / FadeDuration, 0f, 1f );
_processor.Mix = Math.Clamp( startMix + (targetMix - startMix) * t, 0f, 1f );
lastTime = Time.Now;
}
if ( !_cts.IsCancellationRequested )
{
_processor.Mix = targetMix;
}
}
public void OnTriggerExit( Collider other )
{
if ( other.Components.TryGet<Dedugan>( out Dedugan dedugan ) )
{
if ( dedugan.Connection == Dedugan.Local.Connection )
{
_cts?.Cancel();
_cts = new CancellationTokenSource();
_processor.Mix = 0f;
}
}
// _ = UpdateMixAsync(0f).ContinueWith( (_) =>
// {
// if (_processor == null) return;
//
// TargetMixer.Get().RemoveProcessor(_processor);
// _processor = null;
// } );
}
protected override void DrawGizmos()
{
base.DrawGizmos();
Gizmo.Draw.Color = Color.Green;
Gizmo.Draw.LineBBox( Bounds );
}
}