private void AudioSend() { lock (ffmpegLock) { if (ffmpegProcess == null) { return; } if (audioBuffer == null || audioBuffer.Length < encoder.OptimalPacketSize) { audioBuffer = new byte[encoder.OptimalPacketSize]; } UpdatedSubscriptionCache(); while (audioTimer.RemainingBufferDuration < audioBufferLength) { int read = ffmpegProcess.StandardOutput.BaseStream.Read(audioBuffer, 0, encoder.OptimalPacketSize); if (read == 0) { // check for premature connection drop if (ffmpegProcess.HasExited && !hasTriedToReconnectAudio) { var expectedStopLength = GetCurrentSongLength(); if (expectedStopLength != TimeSpan.Zero) { var actualStopPosition = audioTimer.SongPosition; if (actualStopPosition + retryOnDropBeforeEnd < expectedStopLength) { Log.Write(Log.Level.Debug, "Connection to song lost, retrying at {0}", actualStopPosition); hasTriedToReconnectAudio = true; Position = actualStopPosition; return; } } } if (ffmpegProcess.HasExited && audioTimer.RemainingBufferDuration < TimeSpan.Zero && !encoder.HasPacket) { AudioStop(); OnSongEnd?.Invoke(this, new EventArgs()); } return; } hasTriedToReconnectAudio = false; audioTimer.PushBytes(read); if (isStall) { stallCount++; if (stallCount % StallCountInterval == 0) { stallNoErrorCount++; } if (stallNoErrorCount > StallNoErrorCountMax) { stallCount = 0; isStall = false; break; } } AudioModifier.AdjustVolume(audioBuffer, read, volume); encoder.PushPCMAudio(audioBuffer, read); Tuple <byte[], int> encodedArr; while ((encodedArr = encoder.GetPacket()) != null) { if (channelSubscriptionsCache.Length == 0 && clientSubscriptionsCache.Length == 0) { tsFullClient.SendAudio(encodedArr.Item1, encodedArr.Item2, encoder.Codec); } else { tsFullClient.SendAudioWhisper(encodedArr.Item1, encodedArr.Item2, encoder.Codec, channelSubscriptionsCache, clientSubscriptionsCache); } } } } }
private void AudioSend() { lock (ffmpegLock) { if (ffmpegProcess == null) { return; } if (audioBuffer == null || audioBuffer.Length < encoder.OptimalPacketSize) { audioBuffer = new byte[encoder.OptimalPacketSize]; } UpdatedSubscriptionCache(); while (audioTimer.RemainingBufferDuration < audioBufferLength) { int read = ffmpegProcess.StandardOutput.BaseStream.Read(audioBuffer, 0, encoder.OptimalPacketSize); if (read == 0) { // check for premature connection drop if (ffmpegProcess.HasExited && !hasTriedToReconnectAudio) { var expectedStopLength = GetCurrentSongLength(); if (expectedStopLength != TimeSpan.Zero) { var actualStopPosition = audioTimer.SongPosition; if (actualStopPosition + retryOnDropBeforeEnd < expectedStopLength) { Log.Write(Log.Level.Debug, "Connection to song lost, retrying at {0}", actualStopPosition); hasTriedToReconnectAudio = true; Position = actualStopPosition; return; } } } if (ffmpegProcess.HasExited && audioTimer.RemainingBufferDuration < TimeSpan.Zero && !encoder.HasPacket) { AudioStop(); OnSongEnd?.Invoke(this, new EventArgs()); } return; } hasTriedToReconnectAudio = false; audioTimer.PushBytes(read); bool doSend = true; switch (SendMode) { case TargetSendMode.None: doSend = false; break; case TargetSendMode.Voice: break; case TargetSendMode.Whisper: case TargetSendMode.WhisperGroup: if (isStall) { if (++stallCount % StallCountInterval == 0) { stallNoErrorCount++; if (stallNoErrorCount > StallNoErrorCountMax) { stallCount = 0; isStall = false; } } else { doSend = false; } } if (SendMode == TargetSendMode.Whisper) { doSend &= channelSubscriptionsCache.Length > 0 || clientSubscriptionsCache.Length > 0; } break; default: throw new InvalidOperationException(); } // Save cpu when we know there is noone to send to if (!doSend) { break; } AudioModifier.AdjustVolume(audioBuffer, read, volume); encoder.PushPcmAudio(audioBuffer, read); while (encoder.HasPacket) { var packet = encoder.GetPacket(); switch (SendMode) { case TargetSendMode.Voice: tsFullClient.SendAudio(packet.Array, packet.Length, encoder.Codec); break; case TargetSendMode.Whisper: tsFullClient.SendAudioWhisper(packet.Array, packet.Length, encoder.Codec, channelSubscriptionsCache, clientSubscriptionsCache); break; case TargetSendMode.WhisperGroup: tsFullClient.SendAudioGroupWhisper(packet.Array, packet.Length, encoder.Codec, GroupWhisperType, GroupWhisperTarget); break; } encoder.ReturnPacket(packet.Array); } } } }
private void AudioSend() { lock (ffmpegLock) { if (ffmpegProcess == null) { return; } if (audioBuffer == null || audioBuffer.Length < encoder.OptimalPacketSize) { audioBuffer = new byte[encoder.OptimalPacketSize]; } UpdatedSubscriptionCache(); while (audioTimer.BufferLength < audioBufferLength) { int read = ffmpegProcess.StandardOutput.BaseStream.Read(audioBuffer, 0, encoder.OptimalPacketSize); if (read == 0) { if (!ffmpegProcess.HasExited) { return; } if (audioTimer.BufferLength < TimeSpan.Zero && !encoder.HasPacket) { AudioStop(); OnSongEnd?.Invoke(this, new EventArgs()); } return; } audioTimer.PushBytes(read); if (isStall) { stallCount++; if (stallCount % StallCountInterval == 0) { stallNoErrorCount++; } if (stallNoErrorCount > StallNoErrorCountMax) { stallCount = 0; isStall = false; break; } } AudioModifier.AdjustVolume(audioBuffer, read, volume); encoder.PushPCMAudio(audioBuffer, read); Tuple <byte[], int> encodedArr; while ((encodedArr = encoder.GetPacket()) != null) { if (channelSubscriptionsCache.Length == 0 && clientSubscriptionsCache.Length == 0) { tsFullClient.SendAudio(encodedArr.Item1, encodedArr.Item2, encoder.Codec); } else { tsFullClient.SendAudioWhisper(encodedArr.Item1, encodedArr.Item2, encoder.Codec, channelSubscriptionsCache, clientSubscriptionsCache); } } } } }