mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-06 05:18:26 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
113 lines
2.7 KiB
C#
113 lines
2.7 KiB
C#
using Sandbox.Utility;
|
|
using System.Buffers;
|
|
|
|
namespace Sandbox;
|
|
|
|
internal static class VoiceManager
|
|
{
|
|
static ISteamUser steamUser;
|
|
static byte[] compressedBuffer = new byte[1024 * 32];
|
|
static Memory<byte> compressedMemory = Memory<byte>.Empty;
|
|
|
|
public static Action<Memory<byte>> OnCompressedVoiceData { get; set; }
|
|
|
|
static VoiceManager()
|
|
{
|
|
steamUser = NativeEngine.Steam.SteamUser();
|
|
}
|
|
|
|
static RealTimeSince timeSinceLastHear = 10;
|
|
|
|
public static int SampleRate => 44100;
|
|
public static bool IsValid => steamUser.IsValid;
|
|
public static bool IsListening { get; private set; }
|
|
public static bool IsRecording => timeSinceLastHear < 0.2f;
|
|
|
|
public static bool StartRecording()
|
|
{
|
|
if ( !IsValid ) return false;
|
|
|
|
IsListening = true;
|
|
steamUser.StartVoiceRecording();
|
|
return true;
|
|
}
|
|
|
|
public static bool StopRecording()
|
|
{
|
|
if ( !IsValid ) return false;
|
|
|
|
IsListening = false;
|
|
steamUser.StopVoiceRecording();
|
|
return true;
|
|
}
|
|
|
|
static Superluminal _voiceTick = new Superluminal( "VoiceTick", Color.Yellow );
|
|
|
|
static RealTimeSince timeSinceLastTick = 0;
|
|
public static void Tick()
|
|
{
|
|
using ( _voiceTick.Start() )
|
|
{
|
|
if ( timeSinceLastTick < (1.0f / 30.0f) )
|
|
return;
|
|
|
|
timeSinceLastTick = 0;
|
|
ReadVoice();
|
|
}
|
|
}
|
|
|
|
static unsafe void ReadVoice()
|
|
{
|
|
uint dataSize = 0;
|
|
|
|
// Check if there's any avaliable first, the subsequent call takes 0.1ms even if you're not recording..
|
|
if ( steamUser.GetAvailableVoice( out var _ ) != 0 )
|
|
{
|
|
dataSize = 0;
|
|
compressedMemory = Memory<byte>.Empty;
|
|
return;
|
|
}
|
|
|
|
fixed ( byte* inPtr = compressedBuffer )
|
|
{
|
|
if ( steamUser.GetVoice( true, (IntPtr)inPtr, (uint)compressedBuffer.Length, out dataSize ) != 0 )
|
|
{
|
|
dataSize = 0;
|
|
compressedMemory = Memory<byte>.Empty;
|
|
return;
|
|
}
|
|
|
|
timeSinceLastHear = 0;
|
|
compressedMemory = new Memory<byte>( compressedBuffer, 0, (int)dataSize );
|
|
OnCompressedVoiceData?.Invoke( compressedMemory );
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Uncompress a voice buffer and call ondata with the result
|
|
/// </summary>
|
|
public static unsafe void Uncompress( byte[] buffer, Action<Memory<short>> ondata )
|
|
{
|
|
var shortSize = sizeof( short );
|
|
var outBuffer = ArrayPool<short>.Shared.Rent( Math.Max( 20 * 1024, buffer.Length * 4 ) / shortSize );
|
|
uint byteSize = 0;
|
|
|
|
fixed ( byte* inPtr = buffer )
|
|
fixed ( short* outPtr = outBuffer )
|
|
{
|
|
if ( steamUser.DecompressVoice( (IntPtr)inPtr, (uint)buffer.Length, (IntPtr)outPtr, (uint)(outBuffer.Length * shortSize), out byteSize, (uint)VoiceManager.SampleRate ) == 0 )
|
|
{
|
|
if ( byteSize >= 2 && byteSize % 2 == 0 )
|
|
{
|
|
var memory = new Memory<short>( outBuffer, 0, (int)(byteSize / shortSize) );
|
|
ondata?.Invoke( memory );
|
|
}
|
|
}
|
|
}
|
|
|
|
ArrayPool<short>.Shared.Return( outBuffer );
|
|
}
|
|
|
|
|
|
}
|