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;
using System.Diagnostics; using System.Diagnostics;
using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Facepunch.Steamworks.Test 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] [TestMethod]
public void Name() public void Name()
{ {
@ -82,6 +95,8 @@ public void Update()
} }
} }
static MemoryStream decompressStream = new MemoryStream();
[TestMethod] [TestMethod]
public void GetVoice() public void GetVoice()
{ {
@ -90,14 +105,19 @@ public void GetVoice()
int unCompressed = 0; int unCompressed = 0;
int compressed = 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; client.Voice.WantsRecording = true;
@ -126,9 +146,9 @@ public void GetVoice_Compressed_Only()
{ {
int compressed = 0; int compressed = 0;
client.Voice.OnCompressedData = ( data ) => client.Voice.OnCompressedData = ( ptr, length ) =>
{ {
compressed += data.Length; compressed += length;
}; };
client.Voice.WantsRecording = true; client.Voice.WantsRecording = true;
@ -153,9 +173,9 @@ public void GetVoice_UnCompressed_Only()
{ {
int unCompressed = 0; int unCompressed = 0;
client.Voice.OnUncompressedData = ( data ) => client.Voice.OnUncompressedData = ( ptr, length ) =>
{ {
unCompressed += data.Length; unCompressed += length;
}; };
client.Voice.WantsRecording = true; client.Voice.WantsRecording = true;

View File

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