コード例 #1
0
ファイル: Ts3Full.cs プロジェクト: GAMEBOOK/TS3AudioBot
        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);
                        }
                    }
                }
            }
        }
コード例 #2
0
        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);
                    }
                }
            }
        }
コード例 #3
0
ファイル: Ts3Full.cs プロジェクト: davlast/TS3AudioBot
        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);
                        }
                    }
                }
            }
        }