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"); } }
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; } }
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); } } }
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); } } } }