Voice optimization, fixes

This commit is contained in:
Garry Newman 2016-10-07 11:07:35 +01:00
parent aa1aac50af
commit e56ab1f62a
2 changed files with 114 additions and 61 deletions

View File

@ -1,5 +1,6 @@
using System;
using System.Diagnostics;
using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Facepunch.Steamworks.Test
@ -18,6 +19,18 @@ public void Init()
}
}
[TestMethod]
public void Init_10000()
{
for ( int i = 0; i < 100; i++ )
{
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
{
Assert.IsTrue( client.IsValid );
}
}
}
[TestMethod]
public void Name()
{
@ -82,6 +95,8 @@ public void Update()
}
}
static MemoryStream decompressStream = new MemoryStream();
[TestMethod]
public void GetVoice()
{
@ -90,14 +105,19 @@ public void GetVoice()
int unCompressed = 0;
int compressed = 0;
client.Voice.OnCompressedData = ( data ) =>
client.Voice.OnCompressedData = ( ptr, length ) =>
{
compressed += data.Length;
compressed += length;
if ( !client.Voice.Decompress( ptr, 0, length, decompressStream ) )
{
Assert.Fail( "Decompress returned false" );
}
};
client.Voice.OnUncompressedData = ( data ) =>
client.Voice.OnUncompressedData = ( ptr, length ) =>
{
unCompressed += data.Length;
unCompressed += length;
};
client.Voice.WantsRecording = true;
@ -126,9 +146,9 @@ public void GetVoice_Compressed_Only()
{
int compressed = 0;
client.Voice.OnCompressedData = ( data ) =>
client.Voice.OnCompressedData = ( ptr, length ) =>
{
compressed += data.Length;
compressed += length;
};
client.Voice.WantsRecording = true;
@ -153,9 +173,9 @@ public void GetVoice_UnCompressed_Only()
{
int unCompressed = 0;
client.Voice.OnUncompressedData = ( data ) =>
client.Voice.OnUncompressedData = ( ptr, length ) =>
{
unCompressed += data.Length;
unCompressed += length;
};
client.Voice.WantsRecording = true;

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace Facepunch.Steamworks
@ -15,24 +16,27 @@ public Voice Voice
get
{
if ( _voice == null )
_voice = new Voice { client = this };
_voice = new Voice( this );
return _voice;
}
}
}
public class Voice
public class Voice : IDisposable
{
const int ReadBufferSize = 1024 * 128;
const int UncompressBufferSize = 1024 * 256;
internal Client client;
internal byte[] bufferRegular = new byte[ 1024 * 8 ];
internal uint bufferRegularLastWrite = 0;
internal byte[] bufferCompressed = new byte[ 1024 * 8 ];
internal uint bufferCompressedLastWrite = 0;
internal IntPtr ReadCompressedBuffer;
internal IntPtr ReadUncompressedBuffer;
public Action<byte[]> OnCompressedData;
public Action<byte[]> OnUncompressedData;
internal IntPtr UncompressBuffer;
public Action<IntPtr, int> OnCompressedData;
public Action<IntPtr, int> OnUncompressedData;
/// <summary>
@ -68,6 +72,12 @@ public bool WantsRecording
}
}
/// <summary>
/// The last time voice was detected, recorded
/// </summary>
public DateTime LastVoiceRecordTime { get; private set; }
public TimeSpan TimeSinceLastVoiceRecord { get { return DateTime.Now.Subtract( LastVoiceRecordTime ); } }
public bool IsRecording = false;
@ -76,70 +86,93 @@ public bool WantsRecording
/// </summary>
public uint DesiredSampleRate = 0;
internal unsafe void Update()
public Voice( Client client )
{
this.client = client;
ReadCompressedBuffer = Marshal.AllocHGlobal( ReadBufferSize );
ReadUncompressedBuffer = Marshal.AllocHGlobal( ReadBufferSize );
UncompressBuffer = Marshal.AllocHGlobal( UncompressBufferSize );
}
public void Dispose()
{
Marshal.FreeHGlobal( ReadCompressedBuffer );
Marshal.FreeHGlobal( ReadUncompressedBuffer );
Marshal.FreeHGlobal( UncompressBuffer );
}
internal void Update()
{
if ( OnCompressedData == null && OnUncompressedData == null )
return;
fixed ( byte* pbufferRegular = bufferRegular )
fixed ( byte* pbufferCompressed = bufferCompressed )
uint bufferRegularLastWrite = 0;
uint bufferCompressedLastWrite = 0;
Valve.Steamworks.EVoiceResult result = (Valve.Steamworks.EVoiceResult) client.native.user.GetVoice( OnCompressedData != null, ReadCompressedBuffer, ReadBufferSize, ref bufferCompressedLastWrite,
OnUncompressedData != null, (IntPtr) ReadUncompressedBuffer, ReadBufferSize, ref bufferRegularLastWrite,
DesiredSampleRate == 0 ? OptimalSampleRate : DesiredSampleRate );
Console.WriteLine( result );
IsRecording = true;
if ( result == Valve.Steamworks.EVoiceResult.k_EVoiceResultOK )
{
bufferRegularLastWrite = 0;
bufferCompressedLastWrite = 0;
Valve.Steamworks.EVoiceResult result = (Valve.Steamworks.EVoiceResult) client.native.user.GetVoice( OnCompressedData != null, (IntPtr) pbufferCompressed, (uint) bufferCompressed.Length, ref bufferCompressedLastWrite,
OnUncompressedData != null, (IntPtr) pbufferRegular, (uint) bufferRegular.Length, ref bufferRegularLastWrite,
DesiredSampleRate == 0 ? OptimalSampleRate : DesiredSampleRate );
IsRecording = true;
if ( result == Valve.Steamworks.EVoiceResult.k_EVoiceResultOK )
if ( OnCompressedData != null && bufferCompressedLastWrite > 0 )
{
if ( OnCompressedData != null && bufferCompressedLastWrite > 0 )
{
OnCompressedData( bufferRegular.Take( (int)bufferCompressedLastWrite ).ToArray() );
}
if ( OnUncompressedData != null && bufferRegularLastWrite > 0 )
{
OnUncompressedData( bufferRegular.Take( (int)bufferRegularLastWrite ).ToArray() );
}
OnCompressedData( ReadCompressedBuffer, (int)bufferCompressedLastWrite );
}
if ( result == Valve.Steamworks.EVoiceResult.k_EVoiceResultNotRecording ||
result == Valve.Steamworks.EVoiceResult.k_EVoiceResultNotInitialized )
IsRecording = false;
if ( OnUncompressedData != null && bufferRegularLastWrite > 0 )
{
OnUncompressedData( ReadUncompressedBuffer, (int)bufferRegularLastWrite );
}
LastVoiceRecordTime = DateTime.Now;
}
if ( result == Valve.Steamworks.EVoiceResult.k_EVoiceResultNotRecording ||
result == Valve.Steamworks.EVoiceResult.k_EVoiceResultNotInitialized )
IsRecording = false;
}
public unsafe bool Decompress( byte[] input, MemoryStream output, uint samepleRate = 0 )
{
fixed ( byte* p = input )
{
return Decompress( (IntPtr)p, 0, input.Length, output, samepleRate );
}
}
public unsafe bool Decompress( byte[] input, int inputoffset, int inputsize, MemoryStream output, uint samepleRate = 0 )
public unsafe bool Decompress( IntPtr input, int inputoffset, int inputsize, MemoryStream output, uint samepleRate = 0 )
{
if ( samepleRate == 0 )
samepleRate = OptimalSampleRate;
//
// Guessing the uncompressed size cuz we're dicks
//
uint bytesOut = 0;
var result = (Valve.Steamworks.EVoiceResult) client.native.user.DecompressVoice( (IntPtr)( ((byte*)input) + inputoffset ), (uint) inputsize, UncompressBuffer, UncompressBufferSize, ref bytesOut, samepleRate );
if ( bytesOut > 0 )
output.SetLength( bytesOut );
if ( result == Valve.Steamworks.EVoiceResult.k_EVoiceResultOK )
{
var targetBufferSize = inputsize * 10;
if ( output.Capacity < bytesOut )
output.Capacity = (int) bytesOut;
if ( output.Capacity < targetBufferSize )
output.Capacity = targetBufferSize;
output.SetLength( targetBufferSize );
output.SetLength( bytesOut );
Marshal.Copy( UncompressBuffer, output.GetBuffer(), 0, (int) bytesOut );
return true;
}
fixed ( byte* pout = output.GetBuffer() )
fixed ( byte* p = input )
{
uint bytesOut = 0;
var result = (Valve.Steamworks.EVoiceResult) client.native.user.DecompressVoice( (IntPtr)( p + inputoffset ), (uint) inputsize, (IntPtr) pout, (uint) output.Length, ref bytesOut, (uint)samepleRate );
if ( bytesOut > 0 )
output.SetLength( bytesOut );
return result == Valve.Steamworks.EVoiceResult.k_EVoiceResultOK;
}
return false;
}
}
}