mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-25 14:49:28 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
253 lines
5.0 KiB
C#
253 lines
5.0 KiB
C#
using ExCSS;
|
|
using NativeEngine;
|
|
using Sandbox.Audio;
|
|
|
|
namespace Sandbox;
|
|
|
|
/// <summary>
|
|
/// Enables music playback. Use this for music, not for playing game sounds.
|
|
/// </summary>
|
|
public sealed class MusicPlayer : IDisposable
|
|
{
|
|
/// <summary>
|
|
/// We only use the audio component of the video player.
|
|
/// </summary>
|
|
VideoPlayer native;
|
|
|
|
/// <summary>
|
|
/// Sample rate of the audio being played.
|
|
/// </summary>
|
|
public int SampleRate { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Number of channels of the audio being played.
|
|
/// </summary>
|
|
public int Channels { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Gets the total duration of the video in seconds.
|
|
/// </summary>
|
|
public float Duration => native.Duration;
|
|
|
|
/// <summary>
|
|
/// Gets the current playback time in seconds.
|
|
/// </summary>
|
|
public float PlaybackTime => native.PlaybackTime;
|
|
|
|
/// <summary>
|
|
/// Invoked when the audio has finished playing.
|
|
/// </summary>
|
|
public Action OnFinished { get; set; }
|
|
|
|
/// <summary>
|
|
/// Invoked when the audio has repeated.
|
|
/// </summary>
|
|
public Action OnRepeated { get; set; }
|
|
|
|
/// <summary>
|
|
/// Place the listener at 0,0,0 facing 1,0,0.
|
|
/// </summary>
|
|
public bool ListenLocal
|
|
{
|
|
get => native.Audio.ListenLocal;
|
|
set => native.Audio.ListenLocal = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Position of the sound.
|
|
/// </summary>
|
|
public Vector3 Position
|
|
{
|
|
get => native.Audio.Position;
|
|
set => native.Audio.Position = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Pause playback of audio.
|
|
/// </summary>
|
|
public bool Paused
|
|
{
|
|
get => native.IsPaused;
|
|
set
|
|
{
|
|
if ( value )
|
|
{
|
|
native.Pause();
|
|
}
|
|
else
|
|
{
|
|
native.Resume();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Audio will repeat when reaching the end.
|
|
/// </summary>
|
|
public bool Repeat
|
|
{
|
|
get => native.Repeat;
|
|
set => native.Repeat = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Change the volume of this music.
|
|
/// </summary>
|
|
public float Volume
|
|
{
|
|
get => native.Audio.Volume;
|
|
set => native.Audio.Volume = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enables lipsync processing.
|
|
/// </summary>
|
|
public bool LipSync
|
|
{
|
|
get => native.Audio.LipSync;
|
|
set => native.Audio.LipSync = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Which mixer do we want to write to
|
|
/// </summary>
|
|
public Mixer TargetMixer
|
|
{
|
|
get => native.Audio.TargetMixer;
|
|
set => native.Audio.TargetMixer = value;
|
|
}
|
|
|
|
/// <inheritdoc cref="SoundHandle.Distance"/>
|
|
public float Distance
|
|
{
|
|
get => native.Audio.Distance;
|
|
set => native.Audio.Distance = value;
|
|
}
|
|
|
|
/// <inheritdoc cref="SoundHandle.Falloff"/>
|
|
public Curve Falloff
|
|
{
|
|
get => native.Audio.Falloff;
|
|
set => native.Audio.Falloff = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// A list of 15 lipsync viseme weights. Requires <see cref="LipSync"/> to be enabled.
|
|
/// </summary>
|
|
public IReadOnlyList<float> Visemes => native.Audio.Visemes;
|
|
|
|
/// <summary>
|
|
/// Get title of the track.
|
|
/// </summary>
|
|
public string Title
|
|
{
|
|
get
|
|
{
|
|
var title = GetMeta( "title" );
|
|
return string.IsNullOrWhiteSpace( title ) ? GetMeta( "StreamTitle" ) : title;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 512 FFT magnitudes used for audio visualization.
|
|
/// </summary>
|
|
public ReadOnlySpan<float> Spectrum => GetSpectrum();
|
|
|
|
/// <summary>
|
|
/// Approximate measure of audio loudness.
|
|
/// </summary>
|
|
public float Amplitude => native.Audio.GetAmplitude();
|
|
|
|
private unsafe ReadOnlySpan<float> GetSpectrum()
|
|
{
|
|
return native.Audio.GetSpectrum();
|
|
}
|
|
|
|
internal MusicPlayer()
|
|
{
|
|
native = new VideoPlayer();
|
|
native.OnRepeated += OnRepeatInternal;
|
|
native.OnFinished += OnFinishedInternal;
|
|
|
|
// MusicPlayer used to have different defaults than VideoPlayer, need to make sure they are still set
|
|
native.Audio.ListenLocal = false;
|
|
native.Audio.Position = Vector3.Zero;
|
|
native.Audio.Volume = 1.0f;
|
|
native.Audio.LipSync = false;
|
|
}
|
|
|
|
~MusicPlayer()
|
|
{
|
|
MainThread.QueueDispose( this );
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
native?.Dispose();
|
|
native.OnRepeated -= OnRepeatInternal;
|
|
native.OnFinished -= OnFinishedInternal;
|
|
|
|
GC.SuppressFinalize( this );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Plays a music stream from a URL.
|
|
/// </summary>
|
|
public static MusicPlayer PlayUrl( string url )
|
|
{
|
|
var player = new MusicPlayer();
|
|
player.native.Play( url );
|
|
return player;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Plays a music file from a relative path.
|
|
/// </summary>
|
|
public static MusicPlayer Play( BaseFileSystem filesystem, string path )
|
|
{
|
|
var player = new MusicPlayer();
|
|
player.native.Play( filesystem, path );
|
|
return player;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stops audio playback.
|
|
/// </summary>
|
|
public void Stop()
|
|
{
|
|
native.Stop();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the playback position to a specified time in the audio, given in seconds.
|
|
/// </summary>
|
|
public void Seek( float time )
|
|
{
|
|
native.Seek( time );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get meta data string.
|
|
/// </summary>
|
|
internal string GetMeta( string key )
|
|
{
|
|
return native.GetMeta( key );
|
|
}
|
|
|
|
internal void OnFinishedInternal()
|
|
{
|
|
MainThread.Queue( () =>
|
|
{
|
|
OnFinished?.Invoke();
|
|
} );
|
|
}
|
|
|
|
internal void OnRepeatInternal()
|
|
{
|
|
MainThread.Queue( () =>
|
|
{
|
|
OnRepeated?.Invoke();
|
|
} );
|
|
}
|
|
}
|