public void Write(Span <byte> data, Meta meta)
        {
            UpdatedSubscriptionCache();

            var codec = meta?.Codec ?? Codec.OpusMusic;             // XXX a bit hacky

            switch (SendMode)
            {
            case TargetSendMode.None:
                break;

            case TargetSendMode.Voice:
                client.SendAudio(data, codec);
                break;

            case TargetSendMode.Whisper:
                client.SendAudioWhisper(data, codec, channelSubscriptionsCache, clientSubscriptionsCache);
                break;

            case TargetSendMode.WhisperGroup:
                client.SendAudioGroupWhisper(data, codec, GroupWhisperType, GroupWhisperTarget, GroupWhisperTargetId);
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(SendMode), "Unknown send target");
            }
        }
Exemple #2
0
        private static void PlayWorker()
        {
            Stopwatch time = new Stopwatch();

            time.Start();
            int sample     = 0;
            int sampleTime = 960 / (read.WaveFormat.SampleRate / 1000);

            PlayerState = PlayerState.Running;

            while (true)
            {
                ct.ThrowIfCancellationRequested();

                if (paused)
                {
                    SpinWait.SpinUntil(() => { return(!paused); });
                }

                float[] buff = new float[960];
                int     byteNum;
                try
                {
                    byteNum = read.Read(buff, 0, 960);
                }
                catch (Exception e)
                {
                    break;
                }

                try
                {
                    byte[] encoded = new byte[1275];
                    int    len     = encoder.Encode(buff, 0, byteNum, encoded, 0, 1275);

                    sample++;

                    while (!(time.ElapsedMilliseconds >= sample * sampleTime))
                    {
                        ;
                    }
                    ct.ThrowIfCancellationRequested();
                    client.SendAudio(encoded, len, Codec.OpusVoice);
                }
                catch (Exception e)
                {
                    //Console.WriteLine(e);
                    break;
                }
            }

            PlayerState = PlayerState.Stopped;
            if (State != State.Stopped)
            {
                ShiftCue();
                State = State.Playing;
            }
        }
Exemple #3
0
        private static void _waveIn_DataAvailable(object sender, WaveInEventArgs e)
        {
            byte[] soundBuffer = new byte[e.BytesRecorded + _notEncodedBuffer.Length];
            for (int i = 0; i < _notEncodedBuffer.Length; i++)
            {
                soundBuffer[i] = _notEncodedBuffer[i];
            }
            for (int i = 0; i < e.BytesRecorded; i++)
            {
                soundBuffer[i + _notEncodedBuffer.Length] = e.Buffer[i];
            }

            int byteCap         = _bytesPerSegment;
            int segmentCount    = (int)Math.Floor((decimal)soundBuffer.Length / byteCap);
            int segmentsEnd     = segmentCount * byteCap;
            int notEncodedCount = soundBuffer.Length - segmentsEnd;

            _notEncodedBuffer = new byte[notEncodedCount];
            for (int i = 0; i < notEncodedCount; i++)
            {
                _notEncodedBuffer[i] = soundBuffer[segmentsEnd + i];
            }

            for (int i = 0; i < segmentCount; i++)
            {
                byte[] segment = new byte[byteCap];
                for (int j = 0; j < segment.Length; j++)
                {
                    segment[j] = soundBuffer[(i * byteCap) + j];
                }

                short[] inbuff = BytesToShorts(segment);

                try
                {
                    byte[] buff = new byte[1275];
                    int    len  = encoder.Encode(inbuff, 0, 960, buff, 0, 1275);
                    client.SendAudio(buff, len, Codec.OpusVoice);
                }catch (Exception ex)
                {
                    Console.WriteLine(ex);
                }
            }
        }
Exemple #4
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);
                    }
                }
            }
        }