Pretty good audio sync if I do say so myself :)

This commit is contained in:
watsonb8 2019-11-29 22:04:55 -05:00
parent 8bea1d03da
commit 41e853b1c6
7 changed files with 25 additions and 14 deletions

View File

@ -10,7 +10,7 @@ namespace Aurora.Design.Components.MemberList
public partial class MemberList : ContentView public partial class MemberList : ContentView
{ {
private static ObservableCollection<PartyMember> _newSource; private static ObservableCollection<PartyMember> _newSource;
private static NotifyCollectionChangedEventHandler _collectionChangedHandler; // private static NotifyCollectionChangedEventHandler _collectionChangedHandler;
public MemberList() public MemberList()
{ {
InitializeComponent(); InitializeComponent();

View File

@ -172,9 +172,10 @@ namespace Aurora.Design.Views.Party
/// Called by framework when view becomes inactive /// Called by framework when view becomes inactive
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public override async Task OnInactive() public override Task OnInactive()
{ {
_client.StopEvents(); _client.StopEvents();
return Task.FromResult<object>(null);
} }
/// <summary> /// <summary>

View File

@ -10,6 +10,6 @@ service RemoteSyncService {
} }
message Sync { message Sync {
int64 serverTime = 1; int64 serverTimeTicks = 1;
float trackTime = 2; float trackPosition= 2;
} }

View File

@ -23,7 +23,7 @@ namespace Aurora.RemoteImpl
/// <param name="responseStream">The response stream</param> /// <param name="responseStream">The response stream</param>
/// <param name="context">gRPC client context</param> /// <param name="context">gRPC client context</param>
/// <returns></returns> /// <returns></returns>
public async override Task GetEvents(EventsRequest request, public override Task GetEvents(EventsRequest request,
Grpc.Core.IServerStreamWriter<BaseEvent> responseStream, Grpc.Core.IServerStreamWriter<BaseEvent> responseStream,
Grpc.Core.ServerCallContext context) Grpc.Core.ServerCallContext context)
{ {
@ -41,6 +41,7 @@ namespace Aurora.RemoteImpl
EventManager.Instance.AddEventHandler(callback, Combine(new string[] { context.Peer, request.ClientId })); EventManager.Instance.AddEventHandler(callback, Combine(new string[] { context.Peer, request.ClientId }));
are.WaitOne(); are.WaitOne();
return Task.FromResult<object>(null);
} }
/// <summary> /// <summary>

View File

@ -33,13 +33,12 @@ namespace Aurora.RemoteImpl
while (continueSync) while (continueSync)
{ {
Utils.Time networkTime = Utils.TimeUtils.GetNetworkTime();
float length = PlayerService.Instance.CurrentMediaLength; float length = PlayerService.Instance.CurrentMediaLength;
Sync sync = new Sync() Sync sync = new Sync()
{ {
TrackTime = length * PlayerService.Instance.CurrentMediaPosition, TrackPosition = PlayerService.Instance.CurrentMediaPosition,
ServerTime = networkTime.DateTime.Ticks + networkTime.Elapsed.Ticks ServerTimeTicks = Utils.TimeUtils.GetNetworkTime().DateTime.Ticks
}; };
await responseStream.WriteAsync(sync); await responseStream.WriteAsync(sync);
Console.WriteLine("Sent Sync"); Console.WriteLine("Sent Sync");

View File

@ -10,8 +10,10 @@ using LibVLCSharp.Shared;
namespace Aurora.Services.PlayerService namespace Aurora.Services.PlayerService
{ {
public class PlayerService : BaseService<PlayerService> public class PlayerService : BaseService<PlayerService>
{ {
private const long _ticksPerMillisecond = 10000;
private BaseMedia _currentMedia; private BaseMedia _currentMedia;
private MediaPlayer _mediaPlayer; private MediaPlayer _mediaPlayer;
private LibVLC _libvlc; private LibVLC _libvlc;
@ -134,10 +136,10 @@ namespace Aurora.Services.PlayerService
DateTime localTime = time.DateTime; DateTime localTime = time.DateTime;
//Get offset - elapsed time converted to milliseconds //Get offset - elapsed time converted to milliseconds
float offset = (((localTime.Ticks - sync.ServerTime) * 100) / (1000 * 1000));
float length = CurrentMediaLength; float length = CurrentMediaLength;
float newPosition = (sync.TrackTime + (offset + time.Elapsed.Milliseconds)) / length; float offset = (localTime.Ticks - sync.ServerTimeTicks) * _ticksPerMillisecond;
float newPosition = (sync.TrackPosition + offset);
//Adjust position if greater than 10 percent difference //Adjust position if greater than 10 percent difference
float oldPosition = _mediaPlayer.Position; float oldPosition = _mediaPlayer.Position;
@ -145,7 +147,15 @@ namespace Aurora.Services.PlayerService
newPosition - oldPosition < -0.001) newPosition - oldPosition < -0.001)
{ {
_mediaPlayer.Position = newPosition; _mediaPlayer.Position = newPosition;
Console.WriteLine(string.Format("Audio synced: oldPosition: {0} newPosition: {1}", oldPosition, newPosition)); Console.WriteLine(string.Format("**Audio synced**"));
Console.WriteLine(string.Format("Remote Server Time {0}", new DateTime(sync.ServerTimeTicks).ToLongTimeString()));
Console.WriteLine(string.Format("Remote Track Time: {0}", sync.TrackPosition));
Console.WriteLine(string.Format("Local Server Time: {0}", time.DateTime.ToLongTimeString()));
Console.WriteLine(string.Format("Local Track Time: {0}", _mediaPlayer.Position));
Console.WriteLine(string.Format("Offset: {0}", offset));
Console.WriteLine(string.Format("Old Position: {0}", oldPosition));
Console.WriteLine(string.Format("New Position: {0}", newPosition));
} }
} }
} }
@ -158,7 +168,6 @@ namespace Aurora.Services.PlayerService
}); });
syncTask.Start(); syncTask.Start();
// Task syncTask = Task.Run(() => Sync(remoteSyncClient));
} }
} }

View File

@ -45,13 +45,14 @@ namespace Aurora.Utils
socket.ReceiveTimeout = 3000; socket.ReceiveTimeout = 3000;
stopwatch.Start(); stopwatch.Start();
socket.Send(ntpData); socket.Send(ntpData);
stopwatch.Stop();
socket.Receive(ntpData); socket.Receive(ntpData);
socket.Close(); socket.Close();
} }
//Offset to get to the "Transmit Timestamp" field (time at which the reply //Offset to get to the "Transmit Timestamp" field (time at which the reply
//departed the server for the client, in 64-bit timestamp format." //departed the server for the client, in 64-bit timestamp format."
const byte serverReplyTime = 40; byte serverReplyTime = 40;
//Get the seconds part //Get the seconds part
ulong intPart = BitConverter.ToUInt32(ntpData, serverReplyTime); ulong intPart = BitConverter.ToUInt32(ntpData, serverReplyTime);