mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-22 13:19:33 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
171 lines
3.7 KiB
C#
171 lines
3.7 KiB
C#
using System.Runtime.InteropServices;
|
|
using System.Text.Json.Nodes;
|
|
|
|
namespace Sandbox.Audio;
|
|
|
|
/// <summary>
|
|
/// Takes a bunch of samples and processes them. It's common for these to be chained together.
|
|
/// It's also common for the processor to store state between calls.
|
|
/// </summary>
|
|
public abstract partial class AudioProcessor
|
|
{
|
|
/// <summary>
|
|
/// Is this processor active?
|
|
/// </summary>
|
|
[Group( "Processor Settings" )]
|
|
public bool Enabled { get; set; } = true;
|
|
|
|
/// <summary>
|
|
/// Should we fade the influence of this processor in?
|
|
/// </summary>
|
|
[Range( 0, 1 )]
|
|
[Group( "Processor Settings" )]
|
|
public float Mix { get; set; } = 1;
|
|
|
|
private MultiChannelBuffer scratch = new MultiChannelBuffer( 8 );
|
|
|
|
internal Transform _listener;
|
|
|
|
/// <summary>
|
|
/// The listener's position in this frame.
|
|
/// </summary>
|
|
[Hide]
|
|
protected Transform Listener => _listener;
|
|
|
|
/// <summary>
|
|
/// Should process input into output
|
|
/// </summary>
|
|
internal virtual void Process( MultiChannelBuffer input, MultiChannelBuffer output )
|
|
{
|
|
Assert.True( input.ChannelCount <= output.ChannelCount );
|
|
|
|
output.CopyFrom( input );
|
|
ProcessEachChannel( output );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Will process the buffer, and copy it back to output
|
|
/// </summary>
|
|
internal void ProcessInPlace( MultiChannelBuffer inputoutput )
|
|
{
|
|
scratch.Silence();
|
|
Process( inputoutput, scratch );
|
|
|
|
for ( int i = 0; i < inputoutput.ChannelCount; i++ )
|
|
{
|
|
inputoutput.Get( i ).CopyFrom( scratch.Get( i ) );
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called internally to process each channel in a buffer
|
|
/// </summary>
|
|
private unsafe void ProcessEachChannel( MultiChannelBuffer buffer )
|
|
{
|
|
for ( int i = 0; i < buffer.ChannelCount; i++ )
|
|
{
|
|
using ( buffer.Get( i ).DataPointer( out var ptr ) )
|
|
{
|
|
Span<float> memory = new Span<float>( (float*)ptr, AudioEngine.MixBufferSize );
|
|
ProcessSingleChannel( new AudioChannel( i ), memory );
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// For implementations that process each channel individually
|
|
/// </summary>
|
|
protected virtual unsafe void ProcessSingleChannel( AudioChannel channel, Span<float> input )
|
|
{
|
|
|
|
}
|
|
|
|
public JsonObject Serialize()
|
|
{
|
|
var js = Json.SerializeAsObject( this );
|
|
js["__type"] = GetType().Name;
|
|
|
|
return js;
|
|
}
|
|
|
|
public void Deserialize( JsonObject node )
|
|
{
|
|
Json.DeserializeToObject( this, node );
|
|
}
|
|
|
|
public override string ToString() => GetType().Name;
|
|
|
|
protected virtual void OnDestroy()
|
|
{
|
|
|
|
}
|
|
|
|
internal virtual void OnRemovedInternal()
|
|
{
|
|
OnDestroy();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents an audio channel, between 0 and 7. This is used to index into buffers.
|
|
/// This is used rather than an int to avoid unfortuate bugs.
|
|
/// </summary>
|
|
public struct AudioChannel
|
|
{
|
|
public static AudioChannel Left => new AudioChannel( 0 );
|
|
public static AudioChannel Right => new AudioChannel( 1 );
|
|
|
|
internal int channel;
|
|
|
|
public AudioChannel( int i )
|
|
{
|
|
channel = i;
|
|
}
|
|
|
|
public int Get() => channel;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stores a variable per channel
|
|
/// </summary>
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Compiler", "CS0169" )]
|
|
public struct PerChannel<T>
|
|
{
|
|
#pragma warning disable CS0169, CS0649
|
|
private T _0, _1, _2, _3, _4, _5, _6, _7;
|
|
#pragma warning restore CS0169, CS0649
|
|
|
|
private Span<T> Values => MemoryMarshal.CreateSpan( ref _0, 8 );
|
|
|
|
[Obsolete]
|
|
public T[] Value => Values.ToArray();
|
|
|
|
public PerChannel()
|
|
{
|
|
|
|
}
|
|
|
|
public static implicit operator PerChannel<T>( T v )
|
|
{
|
|
PerChannel<T> x = new PerChannel<T>();
|
|
|
|
for ( int i = 0; i < 8; i++ )
|
|
{
|
|
x.Values[i] = v;
|
|
}
|
|
|
|
return x;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the value in a channel
|
|
/// </summary>
|
|
public T Get( AudioChannel i ) => Values[i.channel];
|
|
|
|
/// <summary>
|
|
/// Set the value in a channel
|
|
/// </summary>
|
|
public void Set( AudioChannel i, T value ) => Values[i.channel] = value;
|
|
|
|
}
|