private async Task AudioLoop() { var socket = new UdpSocket(EndPointInfo.SocketEndPoint); var timer = new DriftTimer(TimeSpan.FromMilliseconds(PacketIntervalMilliseconds)); uint timestamp = 0; ushort sequence = 0; try { while (!_globalCancellationToken.IsCancellationRequested) { var packet = GetNextPacket(sequence, timestamp); await timer.Wait(_globalCancellationToken); if (packet.Length > 0) { await socket.Send(packet); } sequence++; timestamp += (uint)SamplesPerPacket; } } catch (TaskCanceledException) { // ignore } catch (Exception ex) { Logger.Error(ex, $"Exception in audio loop: {ex}"); } finally { Logger.Debug("Audio loop stopped."); ClearAudio(); if (TransmittingAudio) { TransmittingAudio = false; Task.Run(() => { OnAudioStop?.Invoke(this, EventArgs.Empty); }).Forget(); } } }
private byte[] GetNextPacket(ushort sequence, uint timestamp) { if (_rawPayloadQueue.TryDequeue(out float[] payload)) { if (!TransmittingAudio) { _packetlessStopwatch.Reset(); TransmittingAudio = true; Task.Run(() => { OnAudioStart?.Invoke(this, EventArgs.Empty); }).Forget(); } return(AssemblePacket(payload, sequence, timestamp)); } else { if (TransmittingAudio) { if (!_packetlessStopwatch.IsRunning) { _packetlessStopwatch.Restart(); } if (_packetlessStopwatch.Elapsed >= TimeSpan.FromSeconds(0.5)) { TransmittingAudio = false; Task.Run(() => { OnAudioStop?.Invoke(this, EventArgs.Empty); }).Forget(); } } } return(new byte[0]); }